Add initial windows runtime setup (#292)

* add initial windows runtime setup

* add cool console output

* doctor support windows base

* add `add-path` and `remove-path` for bin/setup-runtime

* fix composer.ps1 path

* add windows system util

* add windows cmd and doctor base check

* add windows fallback for laravel/prompts

* cd fix [skip ci]

* dir separator and typo fix [skip ci]
This commit is contained in:
Jerry Ma 2023-12-24 20:17:06 +08:00 committed by GitHub
parent d54bf42ba8
commit 539aaefd72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 568 additions and 184 deletions

7
.gitignore vendored
View File

@ -22,9 +22,12 @@ docker/source/
# exclude self-runtime # exclude self-runtime
/bin/* /bin/*
!/bin/spc !/bin/spc*
!/bin/setup-runtime !/bin/setup-runtime*
!/bin/spc-alpine-docker !/bin/spc-alpine-docker
# exclude windows build tools
/php-sdk-binary-tools/
# default test directory # default test directory
/tests/var/ /tests/var/

115
bin/setup-runtime.ps1 Normal file
View File

@ -0,0 +1,115 @@
param (
[string] ${action}
)
function AddToPath {
param (
[string]$pathToAdd
)
$currentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
if ($currentPath -notlike "*$pathToAdd*") {
$newPath = $currentPath + ";$pathToAdd"
[System.Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
Write-Host "Added '$pathToAdd' to Path."
Write-Host "To remove path, use: " -NoNewline
Write-Host "bin/setup-runtime remove-path" -ForegroundColor Cyan
} else {
Write-Host "Path already exists."
}
}
function RemoveFromPath {
param (
[string]$pathToRemove
)
$currentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
if ($currentPath -like "*$pathToRemove*") {
$newPath = $currentPath -replace [regex]::Escape($pathToRemove), ''
[System.Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
Write-Host "Removed Path '$pathToRemove'"
} else {
Write-Host "Path '$pathToRemove' not in Path"
}
}
# working dir
$WorkingDir = (Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Definition))
if ($action -eq 'add-path') {
AddToPath ($WorkingDir + '\runtime')
exit 0
} elseif ($action -eq 'remove-path') {
RemoveFromPath ($WorkingDir + '\runtime')
exit 0
} elseif (-not($action -eq '')) {
Write-Host ("Invalid action: " + $action) -ForegroundColor Red
exit 1
}
# get php 8.1 specific version
$API = (Invoke-WebRequest -Uri "https://www.php.net/releases/index.php?json&version=8.1") | ConvertFrom-Json
# php windows download
$PHPRuntimeUrl = "https://windows.php.net/downloads/releases/php-" + $API.version + "-Win32-vs16-x64.zip"
$ComposerUrl = "https://getcomposer.org/download/latest-stable/composer.phar"
# create dir
New-Item -Path "downloads" -ItemType Directory -Force | Out-Null
# download php
if (-not(Test-Path "downloads\php.zip"))
{
Write-Host "Downloading PHP ..."
Invoke-WebRequest $PHPRuntimeUrl -OutFile "downloads\php.zip"
}
# extract php
New-Item -Path "runtime" -ItemType Directory -Force | Out-Null
Write-Host "Extracting php.zip ..."
Expand-Archive -Path "downloads/php.zip" -DestinationPath "runtime" -Force
# make php.ini
Move-Item -Path "runtime\php.ini-production" -Destination "runtime\php.ini" -Force
$OriginINI = Get-Content -Path "runtime\php.ini" -Raw
$OriginINI = $OriginINI -replace ';extension=openssl', 'extension=openssl'
$OriginINI = $OriginINI -replace ';extension=curl', 'extension=curl'
$OriginINI = $OriginINI -replace ';extension=mbstring', 'extension=mbstring'
$OriginINI = $OriginINI -replace ';extension=sodium', 'extension=sodium'
$OriginINI = $OriginINI -replace ';extension_dir = "./"', ('extension_dir = "' + (Split-Path -Parent $MyInvocation.MyCommand.Definition) + '\..\runtime\ext"')
$OriginINI | Set-Content -Path "runtime\php.ini"
# download composer
if (-not(Test-Path "runtime\composer.phar"))
{
Write-Host "Downloading composer ..."
Invoke-WebRequest $ComposerUrl -OutFile "downloads\composer.phar"
Move-Item -Path "downloads\composer.phar" -Destination "runtime\composer.phar" -Force
}
# create runtime\composer.ps1
$ComposerContent = '
$WorkingDir = (Split-Path -Parent $MyInvocation.MyCommand.Definition)
Start-Process ($WorkingDir + "\php.exe") ($WorkingDir + "\composer.phar " + $args) -NoNewWindow -Wait
'
$ComposerContent | Set-Content -Path 'runtime\composer.ps1' -Encoding UTF8
Write-Host "Successfully downloaded PHP and Composer !" -ForegroundColor Green
Write-Host "Use static-php-cli: " -NoNewline
Write-Host "bin/spc" -ForegroundColor Cyan
Write-Host "Use php: " -NoNewline
Write-Host "runtime/php" -ForegroundColor Cyan
Write-Host "Use composer: " -NoNewline
Write-Host "runtime/composer" -ForegroundColor Cyan
Write-Host ""
Write-Host "Don't forget installing composer dependencies '" -NoNewline
Write-Host "runtime/composer install" -ForegroundColor Cyan -NoNewline
Write-Host "' before using static-php-cli !"
Write-Host ""
Write-Host "If you want to use this PHP for quality tools (like phpstan, php-cs-fixer) or other project,"
Write-Host "or use PHP, Composer as system executable,"
Write-Host "use '" -NoNewline
Write-Host "bin/setup-runtime add-path" -ForegroundColor Cyan -NoNewline
Write-Host "' to add runtime dir in Path."

12
bin/spc.ps1 Normal file
View File

@ -0,0 +1,12 @@
$PHP_Exec = "runtime\php.exe"
if (-not(Test-Path $PHP_Exec)) {
$PHP_Exec = Get-Command php.exe -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Definition
if (-not $PHP_Exec) {
Write-Host "Error: PHP not found, you need to install PHP on your system or use 'bin/setup-runtime'." -ForegroundColor Red
exit 1
}
}
$phpArgs = "bin\spc " + $args
Start-Process $PHP_Exec -ArgumentList $phpArgs -NoNewWindow -Wait

View File

@ -11,7 +11,6 @@
"require": { "require": {
"php": ">= 8.1", "php": ">= 8.1",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-pcntl": "*",
"laravel/prompts": "^0.1.12", "laravel/prompts": "^0.1.12",
"symfony/console": "^5.4 || ^6 || ^7", "symfony/console": "^5.4 || ^6 || ^7",
"zhamao/logger": "^1.0" "zhamao/logger": "^1.0"

403
composer.lock generated
View File

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "198b6207aabb33778c51282cb7aa0c52", "content-hash": "30d9cdb68b65870a63338606f68130f8",
"packages": [ "packages": [
{ {
"name": "illuminate/collections", "name": "illuminate/collections",
"version": "v10.33.0", "version": "v10.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/collections.git", "url": "https://github.com/illuminate/collections.git",
"reference": "766a3b6c3e5c8011b037a147266dcf7f93b21223" "reference": "2677b3962a88640f92dba8a1f4ed38dcaaf13dad"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/illuminate/collections/zipball/766a3b6c3e5c8011b037a147266dcf7f93b21223", "url": "https://api.github.com/repos/illuminate/collections/zipball/2677b3962a88640f92dba8a1f4ed38dcaaf13dad",
"reference": "766a3b6c3e5c8011b037a147266dcf7f93b21223", "reference": "2677b3962a88640f92dba8a1f4ed38dcaaf13dad",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -59,11 +59,11 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2023-11-20T15:45:45+00:00" "time": "2023-12-15T18:25:00+00:00"
}, },
{ {
"name": "illuminate/conditionable", "name": "illuminate/conditionable",
"version": "v10.33.0", "version": "v10.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/conditionable.git", "url": "https://github.com/illuminate/conditionable.git",
@ -109,7 +109,7 @@
}, },
{ {
"name": "illuminate/contracts", "name": "illuminate/contracts",
"version": "v10.33.0", "version": "v10.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/contracts.git", "url": "https://github.com/illuminate/contracts.git",
@ -157,7 +157,7 @@
}, },
{ {
"name": "illuminate/macroable", "name": "illuminate/macroable",
"version": "v10.33.0", "version": "v10.38.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/macroable.git", "url": "https://github.com/illuminate/macroable.git",
@ -414,16 +414,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v6.3.8", "version": "v6.4.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "0d14a9f6d04d4ac38a8cea1171f4554e325dae92" "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/0d14a9f6d04d4ac38a8cea1171f4554e325dae92", "url": "https://api.github.com/repos/symfony/console/zipball/a550a7c99daeedef3f9d23fb82e3531525ff11fd",
"reference": "0d14a9f6d04d4ac38a8cea1171f4554e325dae92", "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -431,7 +431,7 @@
"symfony/deprecation-contracts": "^2.5|^3", "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3",
"symfony/string": "^5.4|^6.0" "symfony/string": "^5.4|^6.0|^7.0"
}, },
"conflict": { "conflict": {
"symfony/dependency-injection": "<5.4", "symfony/dependency-injection": "<5.4",
@ -445,12 +445,16 @@
}, },
"require-dev": { "require-dev": {
"psr/log": "^1|^2|^3", "psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0", "symfony/config": "^5.4|^6.0|^7.0",
"symfony/dependency-injection": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/event-dispatcher": "^5.4|^6.0", "symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/lock": "^5.4|^6.0", "symfony/http-foundation": "^6.4|^7.0",
"symfony/process": "^5.4|^6.0", "symfony/http-kernel": "^6.4|^7.0",
"symfony/var-dumper": "^5.4|^6.0" "symfony/lock": "^5.4|^6.0|^7.0",
"symfony/messenger": "^5.4|^6.0|^7.0",
"symfony/process": "^5.4|^6.0|^7.0",
"symfony/stopwatch": "^5.4|^6.0|^7.0",
"symfony/var-dumper": "^5.4|^6.0|^7.0"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -484,7 +488,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v6.3.8" "source": "https://github.com/symfony/console/tree/v6.4.1"
}, },
"funding": [ "funding": [
{ {
@ -500,7 +504,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-10-31T08:09:35+00:00" "time": "2023-11-30T10:54:28+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@ -983,16 +987,16 @@
}, },
{ {
"name": "symfony/string", "name": "symfony/string",
"version": "v6.3.8", "version": "v6.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/string.git", "url": "https://github.com/symfony/string.git",
"reference": "13880a87790c76ef994c91e87efb96134522577a" "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/13880a87790c76ef994c91e87efb96134522577a", "url": "https://api.github.com/repos/symfony/string/zipball/b45fcf399ea9c3af543a92edf7172ba21174d809",
"reference": "13880a87790c76ef994c91e87efb96134522577a", "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1006,11 +1010,11 @@
"symfony/translation-contracts": "<2.5" "symfony/translation-contracts": "<2.5"
}, },
"require-dev": { "require-dev": {
"symfony/error-handler": "^5.4|^6.0", "symfony/error-handler": "^5.4|^6.0|^7.0",
"symfony/http-client": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0|^7.0",
"symfony/intl": "^6.2", "symfony/intl": "^6.2|^7.0",
"symfony/translation-contracts": "^2.5|^3.0", "symfony/translation-contracts": "^2.5|^3.0",
"symfony/var-exporter": "^5.4|^6.0" "symfony/var-exporter": "^5.4|^6.0|^7.0"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -1049,7 +1053,7 @@
"utf8" "utf8"
], ],
"support": { "support": {
"source": "https://github.com/symfony/string/tree/v6.3.8" "source": "https://github.com/symfony/string/tree/v6.4.0"
}, },
"funding": [ "funding": [
{ {
@ -1065,7 +1069,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-11-09T08:28:21+00:00" "time": "2023-11-28T20:41:49+00:00"
}, },
{ {
"name": "zhamao/logger", "name": "zhamao/logger",
@ -1691,29 +1695,30 @@
}, },
{ {
"name": "captainhook/captainhook", "name": "captainhook/captainhook",
"version": "5.18.3", "version": "5.19.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/captainhookphp/captainhook.git", "url": "https://github.com/captainhookphp/captainhook.git",
"reference": "b7bc503a40ccfe80ea9638e4921b4697669d725f" "reference": "604bfc55fa40d6fe8c0275ca707ee80920b3b3f1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/captainhookphp/captainhook/zipball/b7bc503a40ccfe80ea9638e4921b4697669d725f", "url": "https://api.github.com/repos/captainhookphp/captainhook/zipball/604bfc55fa40d6fe8c0275ca707ee80920b3b3f1",
"reference": "b7bc503a40ccfe80ea9638e4921b4697669d725f", "reference": "604bfc55fa40d6fe8c0275ca707ee80920b3b3f1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"captainhook/secrets": "^0.9.4",
"ext-json": "*", "ext-json": "*",
"ext-spl": "*", "ext-spl": "*",
"ext-xml": "*", "ext-xml": "*",
"php": ">=7.4", "php": ">=8.0",
"sebastianfeldmann/camino": "^0.9.2", "sebastianfeldmann/camino": "^0.9.2",
"sebastianfeldmann/cli": "^3.3", "sebastianfeldmann/cli": "^3.3",
"sebastianfeldmann/git": "^3.9", "sebastianfeldmann/git": "^3.9",
"symfony/console": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0", "symfony/console": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0",
"symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0", "symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0",
"symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0" "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0"
}, },
"replace": { "replace": {
"sebastianfeldmann/captainhook": "*" "sebastianfeldmann/captainhook": "*"
@ -1750,7 +1755,7 @@
} }
], ],
"description": "PHP git hook manager", "description": "PHP git hook manager",
"homepage": "https://github.com/captainhookphp/captainhook", "homepage": "http://php.captainhook.info/",
"keywords": [ "keywords": [
"commit-msg", "commit-msg",
"git", "git",
@ -1762,7 +1767,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/captainhookphp/captainhook/issues", "issues": "https://github.com/captainhookphp/captainhook/issues",
"source": "https://github.com/captainhookphp/captainhook/tree/5.18.3" "source": "https://github.com/captainhookphp/captainhook/tree/5.19.2"
}, },
"funding": [ "funding": [
{ {
@ -1770,7 +1775,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-11-05T13:56:19+00:00" "time": "2023-12-18T14:06:12+00:00"
}, },
{ {
"name": "captainhook/plugin-composer", "name": "captainhook/plugin-composer",
@ -1827,6 +1832,62 @@
}, },
"time": "2022-01-28T04:35:22+00:00" "time": "2022-01-28T04:35:22+00:00"
}, },
{
"name": "captainhook/secrets",
"version": "0.9.5",
"source": {
"type": "git",
"url": "https://github.com/captainhookphp/secrets.git",
"reference": "8aa90d5b9b7892abd11b9da2fc172a7b32b90cbe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/captainhookphp/secrets/zipball/8aa90d5b9b7892abd11b9da2fc172a7b32b90cbe",
"reference": "8aa90d5b9b7892abd11b9da2fc172a7b32b90cbe",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": ">=8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"CaptainHook\\Secrets\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sebastian Feldmann",
"email": "sf@sebastian-feldmann.info"
}
],
"description": "Utility classes to detect secrets",
"keywords": [
"commit-msg",
"keys",
"passwords",
"post-merge",
"prepare-commit-msg",
"secrets",
"tokens"
],
"support": {
"issues": "https://github.com/captainhookphp/secrets/issues",
"source": "https://github.com/captainhookphp/secrets/tree/0.9.5"
},
"funding": [
{
"url": "https://github.com/sponsors/sebastianfeldmann",
"type": "github"
}
],
"time": "2023-11-30T18:10:18+00:00"
},
{ {
"name": "composer/pcre", "name": "composer/pcre",
"version": "3.1.1", "version": "3.1.1",
@ -2178,31 +2239,29 @@
}, },
{ {
"name": "fidry/filesystem", "name": "fidry/filesystem",
"version": "1.1.0", "version": "1.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/theofidry/filesystem.git", "url": "https://github.com/theofidry/filesystem.git",
"reference": "1dd372ab3eb8b84ffe9578bff576b00c9a44ee46" "reference": "8303225d289da1c434f6009743fbe9aad852de0c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/theofidry/filesystem/zipball/1dd372ab3eb8b84ffe9578bff576b00c9a44ee46", "url": "https://api.github.com/repos/theofidry/filesystem/zipball/8303225d289da1c434f6009743fbe9aad852de0c",
"reference": "1dd372ab3eb8b84ffe9578bff576b00c9a44ee46", "reference": "8303225d289da1c434f6009743fbe9aad852de0c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^8.1", "php": "^8.1",
"symfony/filesystem": "^6.3", "symfony/filesystem": "^6.4 || ^7.0",
"thecodingmachine/safe": "^2.0" "thecodingmachine/safe": "^2.0"
}, },
"require-dev": { "require-dev": {
"bamarni/composer-bin-plugin": "^1.4", "bamarni/composer-bin-plugin": "^1.4",
"ergebnis/composer-normalize": "^2.28", "ergebnis/composer-normalize": "^2.28",
"infection/infection": "^0.26", "infection/infection": ">=0.26",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^10.3", "phpunit/phpunit": "^10.3",
"symfony/finder": "^6.3", "symfony/finder": "^6.4 || ^7.0"
"symfony/phpunit-bridge": "^6.2"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -2235,7 +2294,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/theofidry/filesystem/issues", "issues": "https://github.com/theofidry/filesystem/issues",
"source": "https://github.com/theofidry/filesystem/tree/1.1.0" "source": "https://github.com/theofidry/filesystem/tree/1.2.1"
}, },
"funding": [ "funding": [
{ {
@ -2243,7 +2302,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-10-07T07:32:54+00:00" "time": "2023-12-10T13:29:09+00:00"
}, },
{ {
"name": "filp/whoops", "name": "filp/whoops",
@ -2318,16 +2377,16 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.40.0", "version": "v3.41.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "27d2b3265b5d550ec411b4319967ae7cfddfb2e0" "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/27d2b3265b5d550ec411b4319967ae7cfddfb2e0", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8b6ae8dcbaf23f09680643ab832a4a3a260265f6",
"reference": "27d2b3265b5d550ec411b4319967ae7cfddfb2e0", "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2357,8 +2416,6 @@
"php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/accessible-object": "^1.1",
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4",
"phpspec/prophecy": "^1.17",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.6", "phpunit/phpunit": "^9.6",
"symfony/phpunit-bridge": "^6.3.8 || ^7.0", "symfony/phpunit-bridge": "^6.3.8 || ^7.0",
"symfony/yaml": "^5.4 || ^6.0 || ^7.0" "symfony/yaml": "^5.4 || ^6.0 || ^7.0"
@ -2399,7 +2456,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.40.0" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.41.1"
}, },
"funding": [ "funding": [
{ {
@ -2407,7 +2464,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-11-26T09:25:53+00:00" "time": "2023-12-10T19:59:27+00:00"
}, },
{ {
"name": "humbug/box", "name": "humbug/box",
@ -2841,16 +2898,16 @@
}, },
{ {
"name": "nikic/iter", "name": "nikic/iter",
"version": "v2.3.0", "version": "v2.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nikic/iter.git", "url": "https://github.com/nikic/iter.git",
"reference": "d9f88bc04b5b453914373e70c041353d8e67c3f5" "reference": "09cd930fa9ff55747f34c7184532a5a1bd2385b1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nikic/iter/zipball/d9f88bc04b5b453914373e70c041353d8e67c3f5", "url": "https://api.github.com/repos/nikic/iter/zipball/09cd930fa9ff55747f34c7184532a5a1bd2385b1",
"reference": "d9f88bc04b5b453914373e70c041353d8e67c3f5", "reference": "09cd930fa9ff55747f34c7184532a5a1bd2385b1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2887,22 +2944,22 @@
], ],
"support": { "support": {
"issues": "https://github.com/nikic/iter/issues", "issues": "https://github.com/nikic/iter/issues",
"source": "https://github.com/nikic/iter/tree/v2.3.0" "source": "https://github.com/nikic/iter/tree/v2.4.0"
}, },
"time": "2023-07-25T19:55:40+00:00" "time": "2023-12-10T20:43:19+00:00"
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
"version": "v4.17.1", "version": "v4.18.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nikic/PHP-Parser.git", "url": "https://github.com/nikic/PHP-Parser.git",
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999",
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2943,9 +3000,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/nikic/PHP-Parser/issues", "issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0"
}, },
"time": "2023-08-13T19:53:39+00:00" "time": "2023-12-10T21:03:43+00:00"
}, },
{ {
"name": "nunomaduro/collision", "name": "nunomaduro/collision",
@ -3477,16 +3534,16 @@
}, },
{ {
"name": "phpstan/phpdoc-parser", "name": "phpstan/phpdoc-parser",
"version": "1.24.4", "version": "1.24.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git", "url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496" "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/6bd0c26f3786cd9b7c359675cb789e35a8e07496", "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fedf211ff14ec8381c9bf5714e33a7a552dd1acc",
"reference": "6bd0c26f3786cd9b7c359675cb789e35a8e07496", "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3518,22 +3575,22 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types", "description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": { "support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues", "issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.4" "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.5"
}, },
"time": "2023-11-26T18:29:22+00:00" "time": "2023-12-16T09:33:33+00:00"
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "1.10.44", "version": "1.10.50",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "bf84367c53a23f759513985c54ffe0d0c249825b" "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/bf84367c53a23f759513985c54ffe0d0c249825b", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/06a98513ac72c03e8366b5a0cb00750b487032e4",
"reference": "bf84367c53a23f759513985c54ffe0d0c249825b", "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3582,27 +3639,27 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-11-21T16:30:46+00:00" "time": "2023-12-13T10:59:42+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "10.1.9", "version": "10.1.11",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "a56a9ab2f680246adcf3db43f38ddf1765774735" "reference": "78c3b7625965c2513ee96569a4dbb62601784145"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/a56a9ab2f680246adcf3db43f38ddf1765774735", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/78c3b7625965c2513ee96569a4dbb62601784145",
"reference": "a56a9ab2f680246adcf3db43f38ddf1765774735", "reference": "78c3b7625965c2513ee96569a4dbb62601784145",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-dom": "*", "ext-dom": "*",
"ext-libxml": "*", "ext-libxml": "*",
"ext-xmlwriter": "*", "ext-xmlwriter": "*",
"nikic/php-parser": "^4.15", "nikic/php-parser": "^4.18 || ^5.0",
"php": ">=8.1", "php": ">=8.1",
"phpunit/php-file-iterator": "^4.0", "phpunit/php-file-iterator": "^4.0",
"phpunit/php-text-template": "^3.0", "phpunit/php-text-template": "^3.0",
@ -3652,7 +3709,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.9" "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.11"
}, },
"funding": [ "funding": [
{ {
@ -3660,7 +3717,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-11-23T12:23:20+00:00" "time": "2023-12-21T15:38:30+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",
@ -3907,16 +3964,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "10.4.2", "version": "10.5.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "cacd8b9dd224efa8eb28beb69004126c7ca1a1a1" "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/cacd8b9dd224efa8eb28beb69004126c7ca1a1a1", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6fce887c71076a73f32fd3e0774a6833fc5c7f19",
"reference": "cacd8b9dd224efa8eb28beb69004126c7ca1a1a1", "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3956,7 +4013,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "10.4-dev" "dev-main": "10.5-dev"
} }
}, },
"autoload": { "autoload": {
@ -3988,7 +4045,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.4.2" "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.3"
}, },
"funding": [ "funding": [
{ {
@ -4004,7 +4061,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-10-26T07:21:45+00:00" "time": "2023-12-13T07:25:23+00:00"
}, },
{ {
"name": "psr/event-dispatcher", "name": "psr/event-dispatcher",
@ -4302,20 +4359,20 @@
}, },
{ {
"name": "sebastian/complexity", "name": "sebastian/complexity",
"version": "3.1.0", "version": "3.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git", "url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "68cfb347a44871f01e33ab0ef8215966432f6957" "reference": "68ff824baeae169ec9f2137158ee529584553799"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957", "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
"reference": "68cfb347a44871f01e33ab0ef8215966432f6957", "reference": "68ff824baeae169ec9f2137158ee529584553799",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"nikic/php-parser": "^4.10", "nikic/php-parser": "^4.18 || ^5.0",
"php": ">=8.1" "php": ">=8.1"
}, },
"require-dev": { "require-dev": {
@ -4324,7 +4381,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "3.1-dev" "dev-main": "3.2-dev"
} }
}, },
"autoload": { "autoload": {
@ -4348,7 +4405,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues", "issues": "https://github.com/sebastianbergmann/complexity/issues",
"security": "https://github.com/sebastianbergmann/complexity/security/policy", "security": "https://github.com/sebastianbergmann/complexity/security/policy",
"source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0" "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0"
}, },
"funding": [ "funding": [
{ {
@ -4356,7 +4413,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-09-28T11:50:59+00:00" "time": "2023-12-21T08:37:17+00:00"
}, },
{ {
"name": "sebastian/diff", "name": "sebastian/diff",
@ -4631,20 +4688,20 @@
}, },
{ {
"name": "sebastian/lines-of-code", "name": "sebastian/lines-of-code",
"version": "2.0.1", "version": "2.0.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git", "url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d" "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d", "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
"reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d", "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"nikic/php-parser": "^4.10", "nikic/php-parser": "^4.18 || ^5.0",
"php": ">=8.1" "php": ">=8.1"
}, },
"require-dev": { "require-dev": {
@ -4677,7 +4734,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1" "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2"
}, },
"funding": [ "funding": [
{ {
@ -4685,7 +4742,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-08-31T09:25:50+00:00" "time": "2023-12-21T08:38:20+00:00"
}, },
{ {
"name": "sebastian/object-enumerator", "name": "sebastian/object-enumerator",
@ -5148,16 +5205,16 @@
}, },
{ {
"name": "seld/jsonlint", "name": "seld/jsonlint",
"version": "1.10.0", "version": "1.10.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Seldaek/jsonlint.git", "url": "https://github.com/Seldaek/jsonlint.git",
"reference": "594fd6462aad8ecee0b45ca5045acea4776667f1" "reference": "76d449a358ece77d6f1d6331c68453e657172202"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/594fd6462aad8ecee0b45ca5045acea4776667f1", "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/76d449a358ece77d6f1d6331c68453e657172202",
"reference": "594fd6462aad8ecee0b45ca5045acea4776667f1", "reference": "76d449a358ece77d6f1d6331c68453e657172202",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5184,7 +5241,7 @@
{ {
"name": "Jordi Boggiano", "name": "Jordi Boggiano",
"email": "j.boggiano@seld.be", "email": "j.boggiano@seld.be",
"homepage": "http://seld.be" "homepage": "https://seld.be"
} }
], ],
"description": "JSON Linter", "description": "JSON Linter",
@ -5196,7 +5253,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/Seldaek/jsonlint/issues", "issues": "https://github.com/Seldaek/jsonlint/issues",
"source": "https://github.com/Seldaek/jsonlint/tree/1.10.0" "source": "https://github.com/Seldaek/jsonlint/tree/1.10.1"
}, },
"funding": [ "funding": [
{ {
@ -5208,20 +5265,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-05-11T13:16:46+00:00" "time": "2023-12-18T13:03:25+00:00"
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
"version": "v6.3.2", "version": "v6.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/event-dispatcher.git", "url": "https://github.com/symfony/event-dispatcher.git",
"reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e" "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e", "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d76d2632cfc2206eecb5ad2b26cd5934082941b6",
"reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e", "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5238,13 +5295,13 @@
}, },
"require-dev": { "require-dev": {
"psr/log": "^1|^2|^3", "psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0", "symfony/config": "^5.4|^6.0|^7.0",
"symfony/dependency-injection": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/error-handler": "^5.4|^6.0", "symfony/error-handler": "^5.4|^6.0|^7.0",
"symfony/expression-language": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0|^7.0",
"symfony/http-foundation": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0|^7.0",
"symfony/service-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3",
"symfony/stopwatch": "^5.4|^6.0" "symfony/stopwatch": "^5.4|^6.0|^7.0"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -5272,7 +5329,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2" "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.0"
}, },
"funding": [ "funding": [
{ {
@ -5288,7 +5345,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-07-06T06:56:43+00:00" "time": "2023-07-27T06:52:43+00:00"
}, },
{ {
"name": "symfony/event-dispatcher-contracts", "name": "symfony/event-dispatcher-contracts",
@ -5368,16 +5425,16 @@
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v6.3.1", "version": "v6.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59",
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5411,7 +5468,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v6.3.1" "source": "https://github.com/symfony/filesystem/tree/v6.4.0"
}, },
"funding": [ "funding": [
{ {
@ -5427,27 +5484,27 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-06-01T08:30:39+00:00" "time": "2023-07-26T17:27:13+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v6.3.5", "version": "v6.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "a1b31d88c0e998168ca7792f222cbecee47428c4" "reference": "11d736e97f116ac375a81f96e662911a34cd50ce"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/a1b31d88c0e998168ca7792f222cbecee47428c4", "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce",
"reference": "a1b31d88c0e998168ca7792f222cbecee47428c4", "reference": "11d736e97f116ac375a81f96e662911a34cd50ce",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1" "php": ">=8.1"
}, },
"require-dev": { "require-dev": {
"symfony/filesystem": "^6.0" "symfony/filesystem": "^6.0|^7.0"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -5475,7 +5532,7 @@
"description": "Finds files and directories via an intuitive fluent interface", "description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/finder/tree/v6.3.5" "source": "https://github.com/symfony/finder/tree/v6.4.0"
}, },
"funding": [ "funding": [
{ {
@ -5491,20 +5548,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-09-26T12:56:25+00:00" "time": "2023-10-31T17:30:12+00:00"
}, },
{ {
"name": "symfony/options-resolver", "name": "symfony/options-resolver",
"version": "v6.3.0", "version": "v6.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/options-resolver.git", "url": "https://github.com/symfony/options-resolver.git",
"reference": "a10f19f5198d589d5c33333cffe98dc9820332dd" "reference": "22301f0e7fdeaacc14318928612dee79be99860e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/a10f19f5198d589d5c33333cffe98dc9820332dd", "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22301f0e7fdeaacc14318928612dee79be99860e",
"reference": "a10f19f5198d589d5c33333cffe98dc9820332dd", "reference": "22301f0e7fdeaacc14318928612dee79be99860e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5542,7 +5599,7 @@
"options" "options"
], ],
"support": { "support": {
"source": "https://github.com/symfony/options-resolver/tree/v6.3.0" "source": "https://github.com/symfony/options-resolver/tree/v6.4.0"
}, },
"funding": [ "funding": [
{ {
@ -5558,20 +5615,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-05-12T14:21:09+00:00" "time": "2023-08-08T10:16:24+00:00"
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v6.3.4", "version": "v6.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", "url": "https://api.github.com/repos/symfony/process/zipball/191703b1566d97a5425dc969e4350d32b8ef17aa",
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5603,7 +5660,7 @@
"description": "Executes commands in sub-processes", "description": "Executes commands in sub-processes",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/process/tree/v6.3.4" "source": "https://github.com/symfony/process/tree/v6.4.0"
}, },
"funding": [ "funding": [
{ {
@ -5619,11 +5676,11 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-08-07T10:39:22+00:00" "time": "2023-11-17T21:06:49+00:00"
}, },
{ {
"name": "symfony/stopwatch", "name": "symfony/stopwatch",
"version": "v6.3.0", "version": "v6.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/stopwatch.git", "url": "https://github.com/symfony/stopwatch.git",
@ -5665,7 +5722,7 @@
"description": "Provides a way to profile code", "description": "Provides a way to profile code",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/stopwatch/tree/v6.3.0" "source": "https://github.com/symfony/stopwatch/tree/v6.4.0"
}, },
"funding": [ "funding": [
{ {
@ -5685,16 +5742,16 @@
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v6.3.8", "version": "v6.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "81acabba9046550e89634876ca64bfcd3c06aa0a" "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/81acabba9046550e89634876ca64bfcd3c06aa0a", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6",
"reference": "81acabba9046550e89634876ca64bfcd3c06aa0a", "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5707,10 +5764,11 @@
}, },
"require-dev": { "require-dev": {
"ext-iconv": "*", "ext-iconv": "*",
"symfony/console": "^5.4|^6.0", "symfony/console": "^5.4|^6.0|^7.0",
"symfony/http-kernel": "^5.4|^6.0", "symfony/error-handler": "^6.3|^7.0",
"symfony/process": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0|^7.0",
"symfony/uid": "^5.4|^6.0", "symfony/process": "^5.4|^6.0|^7.0",
"symfony/uid": "^5.4|^6.0|^7.0",
"twig/twig": "^2.13|^3.0.4" "twig/twig": "^2.13|^3.0.4"
}, },
"bin": [ "bin": [
@ -5749,7 +5807,7 @@
"dump" "dump"
], ],
"support": { "support": {
"source": "https://github.com/symfony/var-dumper/tree/v6.3.8" "source": "https://github.com/symfony/var-dumper/tree/v6.4.0"
}, },
"funding": [ "funding": [
{ {
@ -5765,7 +5823,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-11-08T10:42:36+00:00" "time": "2023-11-09T08:28:32+00:00"
}, },
{ {
"name": "thecodingmachine/safe", "name": "thecodingmachine/safe",
@ -6022,9 +6080,8 @@
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": ">= 8.1", "php": ">= 8.1",
"ext-mbstring": "*", "ext-mbstring": "*"
"ext-pcntl": "*"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.2.0" "plugin-api-version": "2.6.0"
} }

View File

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace SPC\builder\windows;
class SystemUtil
{
/**
* @param string $name 命令名称
* @param array $paths 寻找的目标路径(如果不传入,则使用环境变量 PATH
* @return null|string 找到了返回命令路径,找不到返回 null
*/
public static function findCommand(string $name, array $paths = []): ?string
{
if (!$paths) {
$paths = explode(PATH_SEPARATOR, getenv('Path'));
}
foreach ($paths as $path) {
if (file_exists($path . DIRECTORY_SEPARATOR . $name)) {
return $path . DIRECTORY_SEPARATOR . $name;
}
}
return null;
}
}

View File

@ -4,13 +4,17 @@ declare(strict_types=1);
namespace SPC\command; namespace SPC\command;
use Laravel\Prompts\ConfirmPrompt;
use Laravel\Prompts\Prompt;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use SPC\ConsoleApplication; use SPC\ConsoleApplication;
use SPC\exception\ExceptionHandler; use SPC\exception\ExceptionHandler;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use ZM\Logger\ConsoleLogger; use ZM\Logger\ConsoleLogger;
abstract class BaseCommand extends Command abstract class BaseCommand extends Command
@ -78,6 +82,15 @@ abstract class BaseCommand extends Command
{ {
$this->input = $input; $this->input = $input;
$this->output = $output; $this->output = $output;
// windows fallback
Prompt::fallbackWhen(PHP_OS_FAMILY === 'Windows');
ConfirmPrompt::fallbackUsing(function (ConfirmPrompt $prompt) use ($input, $output) {
$helper = new QuestionHelper();
$case = $prompt->default ? ' [Y/n] ' : ' [y/N] ';
$question = new ConfirmationQuestion($prompt->label . $case, $prompt->default);
return $helper->ask($input, $output, $question);
});
if ($this->shouldExecute()) { if ($this->shouldExecute()) {
try { try {
return $this->handle(); return $this->handle();

View File

@ -75,8 +75,9 @@ class DoctorCommand extends BaseCommand
} catch (\Throwable $e) { } catch (\Throwable $e) {
$this->output->writeln('<error>' . $e->getMessage() . '</error>'); $this->output->writeln('<error>' . $e->getMessage() . '</error>');
pcntl_signal(SIGINT, SIG_IGN); if (extension_loaded('pcntl')) {
pcntl_signal(SIGINT, SIG_IGN);
}
return static::FAILURE; return static::FAILURE;
} }

View File

@ -34,12 +34,23 @@ final class CheckListHandler
*/ */
public function emitFix(OutputInterface $output, CheckResult $result): void public function emitFix(OutputInterface $output, CheckResult $result): void
{ {
pcntl_signal(SIGINT, function () use ($output) { if (PHP_OS_FAMILY === 'Windows') {
$output->writeln('<error>You cancelled fix</error>'); sapi_windows_set_ctrl_handler(function () use ($output) {
}); $output->writeln('<error>You cancelled fix</error>');
});
} elseif (extension_loaded('pcntl')) {
pcntl_signal(SIGINT, function () use ($output) {
$output->writeln('<error>You cancelled fix</error>');
});
}
$fix_result = call_user_func($this->fix_map[$result->getFixItem()], ...$result->getFixParams()); $fix_result = call_user_func($this->fix_map[$result->getFixItem()], ...$result->getFixParams());
pcntl_signal(SIGINT, SIG_IGN);
if (PHP_OS_FAMILY === 'Windows') {
sapi_windows_set_ctrl_handler(null);
} elseif (extension_loaded('pcntl')) {
pcntl_signal(SIGINT, SIG_IGN);
}
if ($fix_result) { if ($fix_result) {
$output->writeln('<info>Fix done</info>'); $output->writeln('<info>Fix done</info>');

View File

@ -16,8 +16,8 @@ class OSCheckList
#[AsCheckItem('if current OS are supported', level: 999)] #[AsCheckItem('if current OS are supported', level: 999)]
public function checkOS(): ?CheckResult public function checkOS(): ?CheckResult
{ {
if (!in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'BSD'])) { if (!in_array(PHP_OS_FAMILY, ['Darwin', 'Linux', 'BSD', 'Windows'])) {
return CheckResult::fail('Current OS is not supported'); return CheckResult::fail('Current OS is not supported: ' . PHP_OS_FAMILY);
} }
$distro = PHP_OS_FAMILY === 'Linux' ? (' ' . SystemUtil::getOSRelease()['dist']) : ''; $distro = PHP_OS_FAMILY === 'Linux' ? (' ' . SystemUtil::getOSRelease()['dist']) : '';
return CheckResult::ok(PHP_OS_FAMILY . ' ' . php_uname('m') . $distro . ', supported'); return CheckResult::ok(PHP_OS_FAMILY . ' ' . php_uname('m') . $distro . ', supported');

View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace SPC\doctor\item;
use SPC\builder\windows\SystemUtil;
use SPC\doctor\AsCheckItem;
use SPC\doctor\AsFixItem;
use SPC\doctor\CheckResult;
use SPC\exception\RuntimeException;
class WindowsToolCheckList
{
#[AsCheckItem('if git are installed', limit_os: 'Windows', level: 999)]
public function checkGit(): ?CheckResult
{
if (SystemUtil::findCommand('git.exe') === null) {
return CheckResult::fail('Git not installed, please install git for windows manually, see: https://git-scm.com/download/win');
// return CheckResult::fail('Git not installed, see https://static-php.dev/en/guide/windows-setup.html');
}
return CheckResult::ok();
}
#[AsCheckItem('if php-sdk-binary-tools are downloaded', limit_os: 'Windows', level: 998)]
public function checkSDK(): ?CheckResult
{
if (!file_exists(PHP_SDK_PATH . DIRECTORY_SEPARATOR . 'phpsdk-starter.bat')) {
return CheckResult::fail('php-sdk-binary-tools not downloaded', 'install-php-sdk');
}
return CheckResult::ok(PHP_SDK_PATH);
}
#[AsFixItem('install-php-sdk')]
public function installPhpSdk(): bool
{
try {
cmd(true)->exec('git clone https://github.com/php/php-sdk-binary-tools.git ' . PHP_SDK_PATH);
} catch (RuntimeException) {
return false;
}
return true;
}
}

View File

@ -17,6 +17,9 @@ class UnixShell
public function __construct(?bool $debug = null) public function __construct(?bool $debug = null)
{ {
if (PHP_OS_FAMILY === 'Windows') {
throw new RuntimeException('Windows cannot use UnixShell');
}
$this->debug = $debug ?? defined('DEBUG_MODE'); $this->debug = $debug ?? defined('DEBUG_MODE');
} }

View File

@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
namespace SPC\util;
use SPC\exception\RuntimeException;
use ZM\Logger\ConsoleColor;
class WindowsCmd
{
private ?string $cd = null;
private bool $debug;
private array $env = [];
public function __construct(?bool $debug = null)
{
if (PHP_OS_FAMILY !== 'Windows') {
throw new RuntimeException('Only windows can use WindowsCmd');
}
$this->debug = $debug ?? defined('DEBUG_MODE');
}
public function cd(string $dir): WindowsCmd
{
logger()->info('Entering dir: ' . $dir);
$c = clone $this;
$c->cd = $dir;
return $c;
}
/**
* @throws RuntimeException
*/
public function exec(string $cmd): WindowsCmd
{
/* @phpstan-ignore-next-line */
logger()->info(ConsoleColor::yellow('[EXEC] ') . ConsoleColor::green($cmd));
if ($this->cd !== null) {
$cmd = 'cd /d ' . escapeshellarg($this->cd) . ' && ' . $cmd;
}
if (!$this->debug) {
$cmd .= ' >nul 2>&1';
}
echo $cmd . PHP_EOL;
f_passthru($cmd);
return $this;
}
public function execWithResult(string $cmd, bool $with_log = true): array
{
if ($with_log) {
/* @phpstan-ignore-next-line */
logger()->info(ConsoleColor::blue('[EXEC] ') . ConsoleColor::green($cmd));
} else {
logger()->debug('Running command with result: ' . $cmd);
}
exec($cmd, $out, $code);
return [$code, $out];
}
public function setEnv(array $env): WindowsCmd
{
$this->env = array_merge($this->env, $env);
return $this;
}
/**
* @throws RuntimeException
*/
public function execWithEnv(string $cmd): WindowsCmd
{
if ($this->getEnvString() !== '') {
return $this->exec($this->getEnvString() . "call {$cmd}");
}
return $this->exec($cmd);
}
private function getEnvString(): string
{
$str = '';
foreach ($this->env as $k => $v) {
$str .= 'set ' . $k . '=' . $v . ' && ';
}
return $str;
}
}

View File

@ -22,6 +22,10 @@ define('SEPARATED_PATH', [
BUILD_ROOT_PATH, BUILD_ROOT_PATH,
]); ]);
if (PHP_OS_FAMILY === 'Windows') {
define('PHP_SDK_PATH', is_string($a = getenv('PHP_SDK_PATH')) ? $a : (WORKING_DIR . DIRECTORY_SEPARATOR . 'php-sdk-binary-tools'));
}
// dangerous command // dangerous command
const DANGER_CMD = [ const DANGER_CMD = [
'rm', 'rm',

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use SPC\exception\WrongUsageException; use SPC\exception\WrongUsageException;
use SPC\util\UnixShell; use SPC\util\UnixShell;
use SPC\util\WindowsCmd;
use ZM\Logger\ConsoleLogger; use ZM\Logger\ConsoleLogger;
/** /**
@ -120,3 +121,8 @@ function shell(?bool $debug = null): UnixShell
{ {
return new UnixShell($debug); return new UnixShell($debug);
} }
function cmd(?bool $debug = null): WindowsCmd
{
return new WindowsCmd($debug);
}