composer update

This commit is contained in:
david 2023-08-12 18:01:13 +08:00
parent 3c992d062b
commit 2c2eb588b8
473 changed files with 29016 additions and 3399 deletions

View File

@ -3,29 +3,15 @@
namespace app\common\exception;
use Throwable;
use Webman\Exception\ExceptionHandler;
use Webman\Http\Request;
use Webman\Http\Response;
/**
* @access private 常驻内存运行,禁止执行器调用
* Class Handler
* @package app\common\exception
*/
class Handler extends ExceptionHandler
class Handler extends \support\exception\Handler
{
/**
* 记录日志
* @param Throwable $exception
*/
public function report(Throwable $exception)
{
//仅调试模式记录日志
if ($this->_debug) {
parent::report($exception);
}
}
/**
* 渲染返回
* @param Request $request
@ -47,7 +33,7 @@ class Handler extends ExceptionHandler
'msg' => $error
];
if ($this->_debug) {
if ($this->debug) {
$rs['traces'] = (string)$exception;
}
return new Response(200, $header, json_encode($rs, JSON_UNESCAPED_UNICODE));

View File

@ -32,8 +32,6 @@
"rhilip/bencode": "^2.1",
"workerman/crontab": "^1.0",
"curl/curl": "^2.3",
"ext-posix": "*",
"ext-pcntl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-curl": "*",

267
composer.lock generated
View File

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ae7ac58c54130cc5d0d5e1814b2068b0",
"content-hash": "3a4cbdb14aff0d848f4d814b5af32a95",
"packages": [
{
"name": "curl/curl",
"version": "2.4.0",
"version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/php-mod/curl.git",
"reference": "ba385e40c5907850c555db24505c127fe29f1e44"
"reference": "c4f8799c471e43b7c782c77d5c6e178d0465e210"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mod/curl/zipball/ba385e40c5907850c555db24505c127fe29f1e44",
"reference": "ba385e40c5907850c555db24505c127fe29f1e44",
"url": "https://api.github.com/repos/php-mod/curl/zipball/c4f8799c471e43b7c782c77d5c6e178d0465e210",
"reference": "c4f8799c471e43b7c782c77d5c6e178d0465e210",
"shasum": ""
},
"require": {
@ -60,34 +60,34 @@
],
"support": {
"issues": "https://github.com/php-mod/curl/issues",
"source": "https://github.com/php-mod/curl/tree/2.4.0"
"source": "https://github.com/php-mod/curl/tree/2.5.0"
},
"time": "2022-08-29T08:52:24+00:00"
"time": "2022-12-14T13:27:59+00:00"
},
{
"name": "doctrine/inflector",
"version": "2.0.5",
"version": "2.0.8",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "ade2b3bbfb776f27f0558e26eed43b5d9fe1b392"
"reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/ade2b3bbfb776f27f0558e26eed43b5d9fe1b392",
"reference": "ade2b3bbfb776f27f0558e26eed43b5d9fe1b392",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
"reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"doctrine/coding-standard": "^11.0",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^8.5 || ^9.5",
"vimeo/psalm": "^4.25"
"vimeo/psalm": "^4.25 || ^5.4"
},
"type": "library",
"autoload": {
@ -137,7 +137,7 @@
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.0.5"
"source": "https://github.com/doctrine/inflector/tree/2.0.8"
},
"funding": [
{
@ -153,28 +153,28 @@
"type": "tidelift"
}
],
"time": "2022-09-07T09:01:28+00:00"
"time": "2023-06-16T13:40:37+00:00"
},
{
"name": "graham-campbell/result-type",
"version": "v1.1.0",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/GrahamCampbell/Result-Type.git",
"reference": "a878d45c1914464426dc94da61c9e1d36ae262a8"
"reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/a878d45c1914464426dc94da61c9e1d36ae262a8",
"reference": "a878d45c1914464426dc94da61c9e1d36ae262a8",
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831",
"reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"phpoption/phpoption": "^1.9"
"phpoption/phpoption": "^1.9.1"
},
"require-dev": {
"phpunit/phpunit": "^8.5.28 || ^9.5.21"
"phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12"
},
"type": "library",
"autoload": {
@ -203,7 +203,7 @@
],
"support": {
"issues": "https://github.com/GrahamCampbell/Result-Type/issues",
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.0"
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.1"
},
"funding": [
{
@ -215,7 +215,7 @@
"type": "tidelift"
}
],
"time": "2022-07-30T15:56:11+00:00"
"time": "2023-02-25T20:23:15+00:00"
},
{
"name": "ledccn/bittorrentclient",
@ -270,16 +270,16 @@
},
{
"name": "monolog/monolog",
"version": "2.8.0",
"version": "2.9.1",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "720488632c590286b88b80e62aa3d3d551ad4a50"
"reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/720488632c590286b88b80e62aa3d3d551ad4a50",
"reference": "720488632c590286b88b80e62aa3d3d551ad4a50",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1",
"reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1",
"shasum": ""
},
"require": {
@ -294,7 +294,7 @@
"doctrine/couchdb": "~1.0@dev",
"elasticsearch/elasticsearch": "^7 || ^8",
"ext-json": "*",
"graylog2/gelf-php": "^1.4.2",
"graylog2/gelf-php": "^1.4.2 || ^2@dev",
"guzzlehttp/guzzle": "^7.4",
"guzzlehttp/psr7": "^2.2",
"mongodb/mongodb": "^1.8",
@ -356,7 +356,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
"source": "https://github.com/Seldaek/monolog/tree/2.8.0"
"source": "https://github.com/Seldaek/monolog/tree/2.9.1"
},
"funding": [
{
@ -368,7 +368,7 @@
"type": "tidelift"
}
],
"time": "2022-07-24T11:55:47+00:00"
"time": "2023-02-06T13:44:46+00:00"
},
{
"name": "nikic/fast-route",
@ -422,24 +422,24 @@
},
{
"name": "phpoption/phpoption",
"version": "1.9.0",
"version": "1.9.1",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/php-option.git",
"reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab"
"reference": "dd3a383e599f49777d8b628dadbb90cae435b87e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dc5ff11e274a90cc1c743f66c9ad700ce50db9ab",
"reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab",
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e",
"reference": "dd3a383e599f49777d8b628dadbb90cae435b87e",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8",
"phpunit/phpunit": "^8.5.28 || ^9.5.21"
"bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12"
},
"type": "library",
"extra": {
@ -481,7 +481,7 @@
],
"support": {
"issues": "https://github.com/schmittjoh/php-option/issues",
"source": "https://github.com/schmittjoh/php-option/tree/1.9.0"
"source": "https://github.com/schmittjoh/php-option/tree/1.9.1"
},
"funding": [
{
@ -493,7 +493,7 @@
"type": "tidelift"
}
],
"time": "2022-07-30T15:51:26+00:00"
"time": "2023-02-25T19:38:58+00:00"
},
{
"name": "psr/container",
@ -600,16 +600,16 @@
},
{
"name": "rhilip/bencode",
"version": "v2.3.1",
"version": "v2.3.3",
"source": {
"type": "git",
"url": "https://github.com/Rhilip/Bencode.git",
"reference": "8ebf93f9213315407bbb91f6aa7d5e5f5efa3892"
"reference": "fd37d13bb745352d40879dbbfa6da85af91e49f1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Rhilip/Bencode/zipball/8ebf93f9213315407bbb91f6aa7d5e5f5efa3892",
"reference": "8ebf93f9213315407bbb91f6aa7d5e5f5efa3892",
"url": "https://api.github.com/repos/Rhilip/Bencode/zipball/fd37d13bb745352d40879dbbfa6da85af91e49f1",
"reference": "fd37d13bb745352d40879dbbfa6da85af91e49f1",
"shasum": ""
},
"require": {
@ -645,22 +645,22 @@
],
"support": {
"issues": "https://github.com/Rhilip/Bencode/issues",
"source": "https://github.com/Rhilip/Bencode/tree/v2.3.1"
"source": "https://github.com/Rhilip/Bencode/tree/v2.3.3"
},
"time": "2022-07-17T11:19:47+00:00"
"time": "2023-05-27T01:47:00+00:00"
},
{
"name": "symfony/console",
"version": "v5.4.13",
"version": "v5.4.26",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be"
"reference": "b504a3d266ad2bb632f196c0936ef2af5ff6e273"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be",
"reference": "3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be",
"url": "https://api.github.com/repos/symfony/console/zipball/b504a3d266ad2bb632f196c0936ef2af5ff6e273",
"reference": "b504a3d266ad2bb632f196c0936ef2af5ff6e273",
"shasum": ""
},
"require": {
@ -725,12 +725,12 @@
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command line",
"command-line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.4.13"
"source": "https://github.com/symfony/console/tree/v5.4.26"
},
"funding": [
{
@ -746,7 +746,7 @@
"type": "tidelift"
}
],
"time": "2022-08-26T13:50:20+00:00"
"time": "2023-07-19T20:11:33+00:00"
},
{
"name": "symfony/deprecation-contracts",
@ -817,16 +817,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
@ -841,7 +841,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -879,7 +879,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
@ -895,20 +895,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
@ -920,7 +920,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -960,7 +960,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
@ -976,20 +976,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
@ -1001,7 +1001,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1044,7 +1044,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
@ -1060,20 +1060,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
@ -1088,7 +1088,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1127,7 +1127,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
@ -1143,20 +1143,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php73",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"shasum": ""
},
"require": {
@ -1165,7 +1165,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1206,7 +1206,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0"
},
"funding": [
{
@ -1222,20 +1222,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": ""
},
"require": {
@ -1244,7 +1244,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1289,7 +1289,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
@ -1305,7 +1305,7 @@
"type": "tidelift"
}
],
"time": "2022-05-10T07:21:04+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/service-contracts",
@ -1370,16 +1370,16 @@
},
{
"name": "symfony/string",
"version": "v5.4.13",
"version": "v5.4.26",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "2900c668a32138a34118740de3e4d5a701801f53"
"reference": "1181fe9270e373537475e826873b5867b863883c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/2900c668a32138a34118740de3e4d5a701801f53",
"reference": "2900c668a32138a34118740de3e4d5a701801f53",
"url": "https://api.github.com/repos/symfony/string/zipball/1181fe9270e373537475e826873b5867b863883c",
"reference": "1181fe9270e373537475e826873b5867b863883c",
"shasum": ""
},
"require": {
@ -1436,7 +1436,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.4.13"
"source": "https://github.com/symfony/string/tree/v5.4.26"
},
"funding": [
{
@ -1452,7 +1452,7 @@
"type": "tidelift"
}
],
"time": "2022-09-01T01:52:16+00:00"
"time": "2023-06-28T12:46:07+00:00"
},
{
"name": "vlucas/phpdotenv",
@ -1536,16 +1536,16 @@
},
{
"name": "webman/console",
"version": "v1.2.15",
"version": "v1.2.37",
"source": {
"type": "git",
"url": "https://github.com/webman-php/console.git",
"reference": "71932aa62427fbd95ef06178704576bc3274102d"
"reference": "c94d7f351ac09435825e1f84a67413cf5caa1a2a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webman-php/console/zipball/71932aa62427fbd95ef06178704576bc3274102d",
"reference": "71932aa62427fbd95ef06178704576bc3274102d",
"url": "https://api.github.com/repos/webman-php/console/zipball/c94d7f351ac09435825e1f84a67413cf5caa1a2a",
"reference": "c94d7f351ac09435825e1f84a67413cf5caa1a2a",
"shasum": ""
},
"require": {
@ -1585,20 +1585,20 @@
"source": "https://github.com/webman-php/console",
"wiki": "http://www.workerman.net/doc/webman"
},
"time": "2022-09-28T07:16:22+00:00"
"time": "2023-07-26T06:31:50+00:00"
},
{
"name": "webman/event",
"version": "v1.0.2",
"version": "v1.0.4",
"source": {
"type": "git",
"url": "https://github.com/webman-php/event.git",
"reference": "db17d2fd6a5a8799f97f587b17a26b814901e01a"
"reference": "f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webman-php/event/zipball/db17d2fd6a5a8799f97f587b17a26b814901e01a",
"reference": "db17d2fd6a5a8799f97f587b17a26b814901e01a",
"url": "https://api.github.com/repos/webman-php/event/zipball/f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7",
"reference": "f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7",
"shasum": ""
},
"type": "library",
@ -1614,22 +1614,22 @@
"description": "Webman event plugin",
"support": {
"issues": "https://github.com/webman-php/event/issues",
"source": "https://github.com/webman-php/event/tree/v1.0.2"
"source": "https://github.com/webman-php/event/tree/v1.0.4"
},
"time": "2022-06-16T06:25:20+00:00"
"time": "2023-03-28T04:01:23+00:00"
},
{
"name": "workerman/crontab",
"version": "v1.0.4",
"version": "v1.0.6",
"source": {
"type": "git",
"url": "https://github.com/walkor/crontab.git",
"reference": "b9280b14941840d1b8542633d60ef303cefe3875"
"reference": "b78f1556f2977715b9cb5653129e6d9cf160d966"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/crontab/zipball/b9280b14941840d1b8542633d60ef303cefe3875",
"reference": "b9280b14941840d1b8542633d60ef303cefe3875",
"url": "https://api.github.com/repos/walkor/crontab/zipball/b78f1556f2977715b9cb5653129e6d9cf160d966",
"reference": "b78f1556f2977715b9cb5653129e6d9cf160d966",
"shasum": ""
},
"require": {
@ -1666,27 +1666,28 @@
"source": "https://github.com/walkor/crontab",
"wiki": "http://doc.workerman.net/"
},
"time": "2022-08-01T10:24:22+00:00"
"time": "2022-10-17T01:59:19+00:00"
},
{
"name": "workerman/webman-framework",
"version": "v1.4.7",
"version": "v1.5.8",
"source": {
"type": "git",
"url": "https://github.com/walkor/webman-framework.git",
"reference": "e9815557f08dffd3a41b54f709a98619aab84f16"
"reference": "1cf2d1c8231dd4acaf88a491170552747f325732"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/webman-framework/zipball/e9815557f08dffd3a41b54f709a98619aab84f16",
"reference": "e9815557f08dffd3a41b54f709a98619aab84f16",
"url": "https://api.github.com/repos/walkor/webman-framework/zipball/1cf2d1c8231dd4acaf88a491170552747f325732",
"reference": "1cf2d1c8231dd4acaf88a491170552747f325732",
"shasum": ""
},
"require": {
"ext-json": "*",
"nikic/fast-route": "^1.3",
"php": ">=7.2",
"psr/container": ">=1.0",
"workerman/workerman": "^4.0.4"
"workerman/workerman": "^4.0.4 || ^5.0.0"
},
"suggest": {
"ext-event": "For better performance. "
@ -1727,30 +1728,20 @@
"source": "https://github.com/walkor/webman-framework",
"wiki": "https://doc.workerman.net/"
},
"funding": [
{
"url": "https://opencollective.com/walkor",
"type": "open_collective"
},
{
"url": "https://www.patreon.com/walkor",
"type": "patreon"
}
],
"time": "2022-09-19T08:03:06+00:00"
"time": "2023-07-21T09:39:36+00:00"
},
{
"name": "workerman/workerman",
"version": "v4.1.3",
"version": "v4.1.13",
"source": {
"type": "git",
"url": "https://github.com/walkor/workerman.git",
"reference": "01028d8008c5691ec38c5f675fc13d76496a6db9"
"reference": "807780ff672775fcd08f89e573a2824e939021ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/workerman/zipball/01028d8008c5691ec38c5f675fc13d76496a6db9",
"reference": "01028d8008c5691ec38c5f675fc13d76496a6db9",
"url": "https://api.github.com/repos/walkor/workerman/zipball/807780ff672775fcd08f89e573a2824e939021ce",
"reference": "807780ff672775fcd08f89e573a2824e939021ce",
"shasum": ""
},
"require": {
@ -1800,7 +1791,7 @@
"type": "patreon"
}
],
"time": "2022-09-23T14:05:12+00:00"
"time": "2023-07-31T05:57:25+00:00"
}
],
"packages-dev": [],
@ -1813,8 +1804,6 @@
"prefer-lowest": false,
"platform": {
"php": ">=7.2",
"ext-posix": "*",
"ext-pcntl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-curl": "*",
@ -1822,5 +1811,5 @@
"ext-simplexml": "*"
},
"platform-dev": [],
"plugin-api-version": "2.0.0"
"plugin-api-version": "2.3.0"
}

View File

@ -12,15 +12,4 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
// 如果你需要自动依赖注入(包括注解注入)。
// 请先运行 composer require php-di/php-di && composer require doctrine/annotations
// 并将下面的代码注释解除,并注释掉最后一行 return new Webman\Container;
/*$builder = new \DI\ContainerBuilder();
$builder->addDefinitions(config('dependence', []));
$builder->useAutowiring(true);
$builder->useAnnotations(true);
return $builder->build();*/
return new Webman\Container;

View File

@ -5,6 +5,5 @@
return [
'' => [
app\middleware\AuthCheck::class,
//support\middleware\AccessControlTest::class,
]
];

View File

@ -0,0 +1,24 @@
<?php
return [
'enable' => true,
'build_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build',
'phar_filename' => 'webman.phar',
'bin_filename' => 'webman.bin',
'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.
'private_key_file' => '', // The file path for certificate or OpenSSL private key file.
'exclude_pattern' => '#^(?!.*(composer.json|/.github/|/.idea/|/.git/|/.setting/|/runtime/|/vendor-bin/|/build/|/vendor/webman/admin/))(.*)$#',
'exclude_files' => [
'.env', 'LICENSE', 'composer.json', 'composer.lock', 'start.php', 'webman.phar', 'webman.bin'
],
'custom_ini' => '
memory_limit = 256M
',
];

View File

@ -0,0 +1,4 @@
<?php
return [
'enable' => true,
];

View File

@ -0,0 +1,17 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return [
Webman\Event\BootStrap::class,
];

View File

@ -0,0 +1,7 @@
<?php
use Webman\Event\EventListCommand;
return [
EventListCommand::class
];

View File

@ -39,12 +39,6 @@ return [
],
]
],
// 其它进程
/*'websocket' => [
'handler' => process\Websocket::class,
'listen' => 'websocket://0.0.0.0:8888',
'count' => 1,
],*/
'IYUUTask' => [
'handler' => process\Task::class
],

View File

@ -1,21 +1,18 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
* 路由配置
*/
use Webman\Http\Request;
use Webman\Route;
Route::any('/test', function ($request) {
return response('test');
Route::fallback(function (Request $request) {
$response = strtoupper($request->method()) === 'OPTIONS' ? response('', 204) : json(['code' => 404, 'msg' => '404 not found']);
$response->withHeaders([
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Origin' => "*",
'Access-Control-Allow-Methods' => '*',
'Access-Control-Allow-Headers' => '*',
]);
return $response;
});
Route::any('/route-test', 'app\controller\Index@index');

View File

@ -1,40 +0,0 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace process;
use Workerman\Connection\TcpConnection;
class Websocket
{
public function onConnect(TcpConnection $connection)
{
echo "onConnect\n";
}
public function onWebSocketConnect(TcpConnection $connection, $http_buffer)
{
echo "onWebSocketConnect\n";
}
public function onMessage(TcpConnection $connection, $data)
{
$connection->send($data);
}
public function onClose(TcpConnection $connection)
{
echo "onClose\n";
}
}

View File

@ -1,55 +0,0 @@
<?php
namespace support;
class Plugin
{
public static function update($event)
{
static::install($event);
}
public static function install($event)
{
static::findHepler();
$operation = $event->getOperation();
$autoload = method_exists($operation, 'getPackage') ? $operation->getPackage()->getAutoload() : $operation->getTargetPackage()->getAutoload();
if (!isset($autoload['psr-4'])) {
return;
}
$namespace = key($autoload['psr-4']);
$install_function = "\\{$namespace}Install::install";
$plugin_const = "\\{$namespace}Install::WEBMAN_PLUGIN";
if (defined($plugin_const) && is_callable($install_function)) {
$install_function();
}
}
protected static function findHepler()
{
// Plugin.php in vendor
$file = __DIR__ . '/../../../../../support/helpers.php';
if (is_file($file)) {
require_once $file;
return;
}
// Plugin.php in webman
require_once __DIR__ . '/helpers.php';
}
public static function uninstall($event)
{
static::findHepler();
$autoload = $event->getOperation()->getPackage()->getAutoload();
if (!isset($autoload['psr-4'])) {
return;
}
$namespace = key($autoload['psr-4']);
$uninstall_function = "\\{$namespace}Install::uninstall";
$plugin_const = "\\{$namespace}Install::WEBMAN_PLUGIN";
if (defined($plugin_const) && is_callable($uninstall_function)) {
$uninstall_function();
}
}
}

View File

@ -16,8 +16,8 @@ use Dotenv\Dotenv;
use support\Log;
use Webman\Bootstrap;
use Webman\Config;
use Webman\Route;
use Webman\Middleware;
use Webman\Route;
use Webman\Util;
$worker = $worker ?? null;
@ -29,18 +29,18 @@ set_error_handler(function ($level, $message, $file = '', $line = 0) {
});
if ($worker) {
register_shutdown_function(function ($start_time) {
if (time() - $start_time <= 1) {
register_shutdown_function(function ($startTime) {
if (time() - $startTime <= 0.1) {
sleep(1);
}
}, time());
}
if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
Dotenv::createUnsafeImmutable(base_path())->load();
if (class_exists('Dotenv\Dotenv') && file_exists(base_path(false) . '/.env')) {
if (method_exists('Dotenv\Dotenv', 'createUnsafeMutable')) {
Dotenv::createUnsafeMutable(base_path(false))->load();
} else {
Dotenv::createMutable(base_path())->load();
Dotenv::createMutable(base_path(false))->load();
}
}
@ -67,30 +67,30 @@ foreach (config('plugin', []) as $firm => $projects) {
}
}
Middleware::load(config('middleware', []), '');
Middleware::load(config('middleware', []));
foreach (config('plugin', []) as $firm => $projects) {
foreach ($projects as $name => $project) {
if (!is_array($project) || $name === 'static') {
continue;
}
Middleware::load($project['middleware'] ?? [], '');
Middleware::load($project['middleware'] ?? []);
}
Middleware::load($projects['middleware'] ?? [], $firm);
if ($static_middlewares = config("plugin.$firm.static.middleware")) {
Middleware::load(['__static__' => $static_middlewares], $firm);
if ($staticMiddlewares = config("plugin.$firm.static.middleware")) {
Middleware::load(['__static__' => $staticMiddlewares], $firm);
}
}
Middleware::load(['__static__' => config('static.middleware', [])], '');
Middleware::load(['__static__' => config('static.middleware', [])]);
foreach (config('bootstrap', []) as $class_name) {
if (!class_exists($class_name)) {
$log = "Warning: Class $class_name setting in config/bootstrap.php not found\r\n";
foreach (config('bootstrap', []) as $className) {
if (!class_exists($className)) {
$log = "Warning: Class $className setting in config/bootstrap.php not found\r\n";
echo $log;
Log::error($log);
continue;
}
/** @var Bootstrap $class_name */
$class_name::start($worker);
/** @var Bootstrap $className */
$className::start($worker);
}
foreach (config('plugin', []) as $firm => $projects) {
@ -98,26 +98,27 @@ foreach (config('plugin', []) as $firm => $projects) {
if (!is_array($project)) {
continue;
}
foreach ($project['bootstrap'] ?? [] as $class_name) {
if (!class_exists($class_name)) {
$log = "Warning: Class $class_name setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
foreach ($project['bootstrap'] ?? [] as $className) {
if (!class_exists($className)) {
$log = "Warning: Class $className setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
echo $log;
Log::error($log);
continue;
}
/** @var Bootstrap $class_name */
$class_name::start($worker);
/** @var Bootstrap $className */
$className::start($worker);
}
}
foreach ($projects['bootstrap'] ?? [] as $class_name) {
if (!class_exists($class_name)) {
$log = "Warning: Class $class_name setting in plugin/$firm/config/bootstrap.php not found\r\n";
foreach ($projects['bootstrap'] ?? [] as $className) {
/** @var string $className */
if (!class_exists($className)) {
$log = "Warning: Class $className setting in plugin/$firm/config/bootstrap.php not found\r\n";
echo $log;
Log::error($log);
continue;
}
/** @var Bootstrap $class_name */
$class_name::start($worker);
/** @var Bootstrap $className */
$className::start($worker);
}
}

View File

@ -17,132 +17,136 @@ use support\Container;
use support\Request;
use support\Response;
use support\Translation;
use support\view\Raw;
use support\view\Blade;
use support\view\Raw;
use support\view\ThinkPHP;
use support\view\Twig;
use Workerman\Worker;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Webman\App;
use Webman\Config;
use Webman\Route;
// Webman version
define('WEBMAN_VERSION', '1.4');
use Workerman\Worker;
// Project base path
define('BASE_PATH', dirname(__DIR__));
/**
* return the program execute directory
* @param string $path
* @return string
*/
function run_path(string $path = ''): string
{
static $runPath = '';
if (!$runPath) {
$runPath = is_phar() ? dirname(Phar::running(false)) : BASE_PATH;
}
return path_combine($runPath, $path);
}
/**
* if the param $path equal false,will return this program current execute directory
* @param string|false $path
* @return string
*/
function base_path($path = ''): string
{
if (false === $path) {
return run_path();
}
return path_combine(BASE_PATH, $path);
}
/**
* App path
* @param string $path
* @return string
*/
function app_path(string $path = ''): string
{
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
}
/**
* Public path
* @param string $path
* @return string
*/
function public_path(string $path = ''): string
{
static $publicPath = '';
if (!$publicPath) {
$publicPath = \config('app.public_path') ?: run_path('public');
}
return path_combine($publicPath, $path);
}
/**
* Config path
* @param string $path
* @return string
*/
function config_path(string $path = ''): string
{
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
}
/**
* Runtime path
* @param string $path
* @return string
*/
function runtime_path(string $path = ''): string
{
static $runtimePath = '';
if (!$runtimePath) {
$runtimePath = \config('app.runtime_path') ?: run_path('runtime');
}
return path_combine($runtimePath, $path);
}
/**
* Generate paths based on given information
* @param string $front
* @param string $back
* @return string
*/
function path_combine(string $front, string $back)
function path_combine(string $front, string $back): string
{
return $front . ($back ? (DIRECTORY_SEPARATOR . ltrim($back, DIRECTORY_SEPARATOR)) : $back);
}
/**
* return the program execute directory
* @param string $path
* @return string
*/
function run_path(string $path = '')
{
static $run_path = '';
if (!$run_path) {
$run_path = \is_phar() ? \dirname(\Phar::running(false)) : BASE_PATH;
}
return \path_combine($run_path, $path);
}
/**
* if the param $path equal false,will return this program current execute directory
* @param string|false $path
* @return false|string
*/
function base_path($path = '')
{
if (false === $path) {
return \run_path();
}
return \path_combine(BASE_PATH, $path);
}
/**
* @param string $path
* @return string
*/
function app_path(string $path = '')
{
return \path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
}
/**
* @param string $path
* @return string
*/
function public_path(string $path = '')
{
static $public_path = '';
if (!$public_path) {
$public_path = \config('app.public_path') ?: \run_path('public');
}
return \path_combine($public_path, $path);
}
/**
* @param string $path
* @return string
*/
function config_path(string $path = '')
{
return \path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
}
/**
* Phar support.
* Compatible with the 'realpath' function in the phar file.
* @param string $path
* @return string
*/
function runtime_path(string $path = '')
{
static $runtime_path = '';
if (!$runtime_path) {
$runtime_path = \config('app.runtime_path') ?: \run_path('runtime');
}
return \path_combine($runtime_path, $path);
}
/**
* Response
* @param int $status
* @param array $headers
* @param string $body
* @return Response
*/
function response($body = '', $status = 200, $headers = [])
function response(string $body = '', int $status = 200, array $headers = []): Response
{
return new Response($status, $headers, $body);
}
/**
* Json response
* @param $data
* @param int $options
* @return Response
*/
function json($data, $options = JSON_UNESCAPED_UNICODE)
function json($data, int $options = JSON_UNESCAPED_UNICODE): Response
{
return new Response(200, ['Content-Type' => 'application/json'], \json_encode($data, $options));
return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
}
/**
* Xml response
* @param $xml
* @return Response
*/
function xml($xml)
function xml($xml): Response
{
if ($xml instanceof SimpleXMLElement) {
$xml = $xml->asXML();
@ -151,25 +155,27 @@ function xml($xml)
}
/**
* Jsonp response
* @param $data
* @param string $callback_name
* @param string $callbackName
* @return Response
*/
function jsonp($data, $callback_name = 'callback')
function jsonp($data, string $callbackName = 'callback'): Response
{
if (!\is_scalar($data) && null !== $data) {
$data = \json_encode($data);
if (!is_scalar($data) && null !== $data) {
$data = json_encode($data);
}
return new Response(200, [], "$callback_name($data)");
return new Response(200, [], "$callbackName($data)");
}
/**
* Redirect response
* @param string $location
* @param int $status
* @param array $headers
* @return Response
*/
function redirect(string $location, int $status = 302, array $headers = [])
function redirect(string $location, int $status = 302, array $headers = []): Response
{
$response = new Response($status, ['Location' => $location]);
if (!empty($headers)) {
@ -179,65 +185,75 @@ function redirect(string $location, int $status = 302, array $headers = [])
}
/**
* @param $template
* View response
* @param string $template
* @param array $vars
* @param null $app
* @param string|null $app
* @param string|null $plugin
* @return Response
*/
function view(string $template, array $vars = [], string $app = null)
function view(string $template, array $vars = [], string $app = null, string $plugin = null): Response
{
$request = \request();
$plugin = $request->plugin ?? '';
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
return new Response(200, [], $handler::render($template, $vars, $app));
return new Response(200, [], $handler::render($template, $vars, $app, $plugin));
}
/**
* Raw view response
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
* @throws Throwable
*/
function raw_view(string $template, array $vars = [], string $app = null)
function raw_view(string $template, array $vars = [], string $app = null): Response
{
return new Response(200, [], Raw::render($template, $vars, $app));
}
/**
* Blade view response
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
*/
function blade_view(string $template, array $vars = [], string $app = null)
function blade_view(string $template, array $vars = [], string $app = null): Response
{
return new Response(200, [], Blade::render($template, $vars, $app));
}
/**
* Think view response
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
*/
function think_view(string $template, array $vars = [], string $app = null)
function think_view(string $template, array $vars = [], string $app = null): Response
{
return new Response(200, [], ThinkPHP::render($template, $vars, $app));
}
/**
* Twig view response
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
function twig_view(string $template, array $vars = [], string $app = null)
function twig_view(string $template, array $vars = [], string $app = null): Response
{
return new Response(200, [], Twig::render($template, $vars, $app));
}
/**
* Get request
* @return \Webman\Http\Request|Request|null
*/
function request()
@ -246,6 +262,7 @@ function request()
}
/**
* Get config
* @param string|null $key
* @param $default
* @return array|mixed|null
@ -256,11 +273,12 @@ function config(string $key = null, $default = null)
}
/**
* Create url
* @param string $name
* @param ...$parameters
* @return string
*/
function route(string $name, ...$parameters)
function route(string $name, ...$parameters): string
{
$route = Route::getByName($name);
if (!$route) {
@ -271,14 +289,15 @@ function route(string $name, ...$parameters)
return $route->url();
}
if (\is_array(\current($parameters))) {
$parameters = \current($parameters);
if (is_array(current($parameters))) {
$parameters = current($parameters);
}
return $route->url($parameters);
}
/**
* Session
* @param mixed $key
* @param mixed $default
* @return mixed
@ -289,14 +308,14 @@ function session($key = null, $default = null)
if (null === $key) {
return $session;
}
if (\is_array($key)) {
if (is_array($key)) {
$session->put($key);
return null;
}
if (\strpos($key, '.')) {
$key_array = \explode('.', $key);
if (strpos($key, '.')) {
$keyArray = explode('.', $key);
$value = $session->all();
foreach ($key_array as $index) {
foreach ($keyArray as $index) {
if (!isset($value[$index])) {
return $default;
}
@ -308,43 +327,44 @@ function session($key = null, $default = null)
}
/**
* Translation
* @param string $id
* @param array $parameters
* @param string|null $domain
* @param string|null $locale
* @return string
*/
function trans(string $id, array $parameters = [], string $domain = null, string $locale = null)
function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string
{
$res = Translation::trans($id, $parameters, $domain, $locale);
return $res === '' ? $id : $res;
}
/**
* @param null|string $locale
* Locale
* @param string|null $locale
* @return string
*/
function locale(string $locale = null)
function locale(string $locale = null): string
{
if (!$locale) {
return Translation::getLocale();
}
Translation::setLocale($locale);
return $locale;
}
/**
* 404 not found
*
* @return Response
*/
function not_found()
function not_found(): Response
{
return new Response(404, [], \file_get_contents(public_path() . '/404.html'));
return new Response(404, [], file_get_contents(public_path() . '/404.html'));
}
/**
* Copy dir.
*
* Copy dir
* @param string $source
* @param string $dest
* @param bool $overwrite
@ -352,46 +372,46 @@ function not_found()
*/
function copy_dir(string $source, string $dest, bool $overwrite = false)
{
if (\is_dir($source)) {
if (is_dir($source)) {
if (!is_dir($dest)) {
\mkdir($dest);
mkdir($dest);
}
$files = \scandir($source);
$files = scandir($source);
foreach ($files as $file) {
if ($file !== "." && $file !== "..") {
\copy_dir("$source/$file", "$dest/$file");
copy_dir("$source/$file", "$dest/$file");
}
}
} else if (\file_exists($source) && ($overwrite || !\file_exists($dest))) {
\copy($source, $dest);
} else if (file_exists($source) && ($overwrite || !file_exists($dest))) {
copy($source, $dest);
}
}
/**
* Remove dir.
*
* Remove dir
* @param string $dir
* @return bool
*/
function remove_dir(string $dir)
function remove_dir(string $dir): bool
{
if (\is_link($dir) || \is_file($dir)) {
return \unlink($dir);
if (is_link($dir) || is_file($dir)) {
return unlink($dir);
}
$files = \array_diff(\scandir($dir), array('.', '..'));
$files = array_diff(scandir($dir), array('.', '..'));
foreach ($files as $file) {
(\is_dir("$dir/$file") && !\is_link($dir)) ? \remove_dir("$dir/$file") : \unlink("$dir/$file");
(is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file");
}
return \rmdir($dir);
return rmdir($dir);
}
/**
* Bind worker
* @param $worker
* @param $class
*/
function worker_bind($worker, $class)
{
$callback_map = [
$callbackMap = [
'onConnect',
'onMessage',
'onClose',
@ -399,27 +419,29 @@ function worker_bind($worker, $class)
'onBufferFull',
'onBufferDrain',
'onWorkerStop',
'onWebSocketConnect'
'onWebSocketConnect',
'onWorkerReload'
];
foreach ($callback_map as $name) {
if (\method_exists($class, $name)) {
foreach ($callbackMap as $name) {
if (method_exists($class, $name)) {
$worker->$name = [$class, $name];
}
}
if (\method_exists($class, 'onWorkerStart')) {
\call_user_func([$class, 'onWorkerStart'], $worker);
if (method_exists($class, 'onWorkerStart')) {
call_user_func([$class, 'onWorkerStart'], $worker);
}
}
/**
* @param $process_name
* Start worker
* @param $processName
* @param $config
* @return void
*/
function worker_start($process_name, $config)
function worker_start($processName, $config)
{
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
$property_map = [
$propertyMap = [
'count',
'user',
'group',
@ -428,81 +450,66 @@ function worker_start($process_name, $config)
'transport',
'protocol',
];
$worker->name = $process_name;
foreach ($property_map as $property) {
$worker->name = $processName;
foreach ($propertyMap as $property) {
if (isset($config[$property])) {
$worker->$property = $config[$property];
}
}
$worker->onWorkerStart = function ($worker) use ($config) {
require_once \base_path() . '/support/bootstrap.php';
foreach ($config['services'] ?? [] as $server) {
if (!\class_exists($server['handler'])) {
echo "process error: class {$server['handler']} not exists\r\n";
continue;
}
$listen = new Worker($server['listen'] ?? null, $server['context'] ?? []);
if (isset($server['listen'])) {
echo "listen: {$server['listen']}\n";
}
$instance = Container::make($server['handler'], $server['constructor'] ?? []);
\worker_bind($listen, $instance);
$listen->listen();
}
require_once base_path('/support/bootstrap.php');
if (isset($config['handler'])) {
if (!\class_exists($config['handler'])) {
if (!class_exists($config['handler'])) {
echo "process error: class {$config['handler']} not exists\r\n";
return;
}
$instance = Container::make($config['handler'], $config['constructor'] ?? []);
\worker_bind($worker, $instance);
worker_bind($worker, $instance);
}
};
}
/**
* Phar support.
* Compatible with the 'realpath' function in the phar file.
*
* @param string $file_path
* Get realpath
* @param string $filePath
* @return string
*/
function get_realpath(string $file_path): string
function get_realpath(string $filePath): string
{
if (\strpos($file_path, 'phar://') === 0) {
return $file_path;
if (strpos($filePath, 'phar://') === 0) {
return $filePath;
} else {
return \realpath($file_path);
return realpath($filePath);
}
}
/**
* Is phar
* @return bool
*/
function is_phar()
function is_phar(): bool
{
return \class_exists(\Phar::class, false) && Phar::running();
return class_exists(Phar::class, false) && Phar::running();
}
/**
* Get cpu count
* @return int
*/
function cpu_count()
function cpu_count(): int
{
// Windows does not support the number of processes setting.
if (\DIRECTORY_SEPARATOR === '\\') {
if (DIRECTORY_SEPARATOR === '\\') {
return 1;
}
$count = 4;
if (\is_callable('shell_exec')) {
if (\strtolower(PHP_OS) === 'darwin') {
$count = (int)\shell_exec('sysctl -n machdep.cpu.core_count');
if (is_callable('shell_exec')) {
if (strtolower(PHP_OS) === 'darwin') {
$count = (int)shell_exec('sysctl -n machdep.cpu.core_count');
} else {
$count = (int)\shell_exec('nproc');
$count = (int)shell_exec('nproc');
}
}
return $count > 0 ? $count : 4;

18
vendor/autoload.php vendored
View File

@ -2,6 +2,24 @@
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit4dfbd30c142d9169bdd5809ad6beb22e::getLoader();

View File

@ -42,30 +42,79 @@ namespace Composer\Autoload;
*/
class ClassLoader
{
/** @var \Closure(string):void */
private static $includeFile;
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
@ -75,28 +124,47 @@ class ClassLoader
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
@ -111,9 +179,11 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
@ -156,11 +226,13 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
@ -204,8 +276,10 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
@ -220,10 +294,12 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
@ -243,6 +319,8 @@ class ClassLoader
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
@ -265,6 +343,8 @@ class ClassLoader
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
@ -285,6 +365,8 @@ class ClassLoader
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
@ -305,6 +387,8 @@ class ClassLoader
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
@ -324,6 +408,8 @@ class ClassLoader
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
@ -338,15 +424,18 @@ class ClassLoader
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
return null;
}
/**
@ -401,6 +490,11 @@ class ClassLoader
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
@ -466,14 +560,26 @@ class ClassLoader
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
}

View File

@ -1,526 +1,352 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
private static $installed = array (
'root' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => '24a29479103cbe2c1113b929790d619e99d20d03',
'name' => 'workerman/webman',
),
'versions' =>
array (
'curl/curl' =>
array (
'pretty_version' => '2.4.0',
'version' => '2.4.0.0',
'aliases' =>
array (
),
'reference' => 'ba385e40c5907850c555db24505c127fe29f1e44',
),
'doctrine/inflector' =>
array (
'pretty_version' => '2.0.5',
'version' => '2.0.5.0',
'aliases' =>
array (
),
'reference' => 'ade2b3bbfb776f27f0558e26eed43b5d9fe1b392',
),
'graham-campbell/result-type' =>
array (
'pretty_version' => 'v1.1.0',
'version' => '1.1.0.0',
'aliases' =>
array (
),
'reference' => 'a878d45c1914464426dc94da61c9e1d36ae262a8',
),
'ledccn/bittorrentclient' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
0 => '9999999-dev',
),
'reference' => '9aead6a8750befb518adec30dd27dc92d3ec88fa',
),
'monolog/monolog' =>
array (
'pretty_version' => '2.8.0',
'version' => '2.8.0.0',
'aliases' =>
array (
),
'reference' => '720488632c590286b88b80e62aa3d3d551ad4a50',
),
'nikic/fast-route' =>
array (
'pretty_version' => 'v1.3.0',
'version' => '1.3.0.0',
'aliases' =>
array (
),
'reference' => '181d480e08d9476e61381e04a71b34dc0432e812',
),
'phpoption/phpoption' =>
array (
'pretty_version' => '1.9.0',
'version' => '1.9.0.0',
'aliases' =>
array (
),
'reference' => 'dc5ff11e274a90cc1c743f66c9ad700ce50db9ab',
),
'psr/container' =>
array (
'pretty_version' => '2.0.2',
'version' => '2.0.2.0',
'aliases' =>
array (
),
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
),
'psr/log' =>
array (
'pretty_version' => '1.1.4',
'version' => '1.1.4.0',
'aliases' =>
array (
),
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
),
'psr/log-implementation' =>
array (
'provided' =>
array (
0 => '1.0.0 || 2.0.0 || 3.0.0',
1 => '1.0|2.0',
),
),
'rhilip/bencode' =>
array (
'pretty_version' => 'v2.3.1',
'version' => '2.3.1.0',
'aliases' =>
array (
),
'reference' => '8ebf93f9213315407bbb91f6aa7d5e5f5efa3892',
),
'symfony/console' =>
array (
'pretty_version' => 'v5.4.13',
'version' => '5.4.13.0',
'aliases' =>
array (
),
'reference' => '3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be',
),
'symfony/deprecation-contracts' =>
array (
'pretty_version' => 'v2.5.2',
'version' => '2.5.2.0',
'aliases' =>
array (
),
'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
),
'symfony/polyfill-ctype' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => '6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4',
),
'symfony/polyfill-intl-grapheme' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => '433d05519ce6990bf3530fba6957499d327395c2',
),
'symfony/polyfill-intl-normalizer' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => '219aa369ceff116e673852dce47c3a41794c14bd',
),
'symfony/polyfill-mbstring' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => '9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e',
),
'symfony/polyfill-php73' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => 'e440d35fa0286f77fb45b79a03fedbeda9307e85',
),
'symfony/polyfill-php80' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => 'cfa0ae98841b9e461207c13ab093d76b0fa7bace',
),
'symfony/service-contracts' =>
array (
'pretty_version' => 'v1.1.2',
'version' => '1.1.2.0',
'aliases' =>
array (
),
'reference' => '191afdcb5804db960d26d8566b7e9a2843cab3a0',
),
'symfony/string' =>
array (
'pretty_version' => 'v5.4.13',
'version' => '5.4.13.0',
'aliases' =>
array (
),
'reference' => '2900c668a32138a34118740de3e4d5a701801f53',
),
'vlucas/phpdotenv' =>
array (
'pretty_version' => 'v5.1.0',
'version' => '5.1.0.0',
'aliases' =>
array (
),
'reference' => '448c76d7a9e30c341ff5bc367a923af74ae18467',
),
'webman/console' =>
array (
'pretty_version' => 'v1.2.15',
'version' => '1.2.15.0',
'aliases' =>
array (
),
'reference' => '71932aa62427fbd95ef06178704576bc3274102d',
),
'webman/event' =>
array (
'pretty_version' => 'v1.0.2',
'version' => '1.0.2.0',
'aliases' =>
array (
),
'reference' => 'db17d2fd6a5a8799f97f587b17a26b814901e01a',
),
'workerman/crontab' =>
array (
'pretty_version' => 'v1.0.4',
'version' => '1.0.4.0',
'aliases' =>
array (
),
'reference' => 'b9280b14941840d1b8542633d60ef303cefe3875',
),
'workerman/webman' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => '24a29479103cbe2c1113b929790d619e99d20d03',
),
'workerman/webman-framework' =>
array (
'pretty_version' => 'v1.4.7',
'version' => '1.4.7.0',
'aliases' =>
array (
),
'reference' => 'e9815557f08dffd3a41b54f709a98619aab84f16',
),
'workerman/workerman' =>
array (
'pretty_version' => 'v4.1.3',
'version' => '4.1.3.0',
'aliases' =>
array (
),
'reference' => '01028d8008c5691ec38c5f675fc13d76496a6db9',
),
),
);
private static $canGetVendors;
private static $installedByVendor = array();
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
public static function isInstalled($packageName)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return true;
}
}
return false;
}
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
public static function getRawData()
{
return self::$installed;
}
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
}
}
}
$installed[] = self::$installed;
return $installed;
}
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = require __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
$installed[] = self::$installed;
return $installed;
}
}

View File

@ -2,7 +2,7 @@
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View File

@ -2,7 +2,7 @@
// autoload_files.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View File

@ -2,7 +2,7 @@
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View File

@ -2,7 +2,7 @@
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View File

@ -22,52 +22,29 @@ class ComposerAutoloaderInit4dfbd30c142d9169bdd5809ad6beb22e
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit4dfbd30c142d9169bdd5809ad6beb22e', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit4dfbd30c142d9169bdd5809ad6beb22e', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit4dfbd30c142d9169bdd5809ad6beb22e::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit4dfbd30c142d9169bdd5809ad6beb22e::getInitializer($loader));
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit4dfbd30c142d9169bdd5809ad6beb22e::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire4dfbd30c142d9169bdd5809ad6beb22e($fileIdentifier, $file);
$filesToLoad = \Composer\Autoload\ComposerStaticInit4dfbd30c142d9169bdd5809ad6beb22e::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}, null, null);
foreach ($filesToLoad as $fileIdentifier => $file) {
$requireFile($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequire4dfbd30c142d9169bdd5809ad6beb22e($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
}
}

View File

@ -2,17 +2,17 @@
"packages": [
{
"name": "curl/curl",
"version": "2.4.0",
"version_normalized": "2.4.0.0",
"version": "2.5.0",
"version_normalized": "2.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-mod/curl.git",
"reference": "ba385e40c5907850c555db24505c127fe29f1e44"
"reference": "c4f8799c471e43b7c782c77d5c6e178d0465e210"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mod/curl/zipball/ba385e40c5907850c555db24505c127fe29f1e44",
"reference": "ba385e40c5907850c555db24505c127fe29f1e44",
"url": "https://api.github.com/repos/php-mod/curl/zipball/c4f8799c471e43b7c782c77d5c6e178d0465e210",
"reference": "c4f8799c471e43b7c782c77d5c6e178d0465e210",
"shasum": ""
},
"require": {
@ -22,7 +22,7 @@
"require-dev": {
"yoast/phpunit-polyfills": "^0.2.0"
},
"time": "2022-08-29T08:52:24+00:00",
"time": "2022-12-14T13:27:59+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -57,37 +57,37 @@
],
"support": {
"issues": "https://github.com/php-mod/curl/issues",
"source": "https://github.com/php-mod/curl/tree/2.4.0"
"source": "https://github.com/php-mod/curl/tree/2.5.0"
},
"install-path": "../curl/curl"
},
{
"name": "doctrine/inflector",
"version": "2.0.5",
"version_normalized": "2.0.5.0",
"version": "2.0.8",
"version_normalized": "2.0.8.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "ade2b3bbfb776f27f0558e26eed43b5d9fe1b392"
"reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/ade2b3bbfb776f27f0558e26eed43b5d9fe1b392",
"reference": "ade2b3bbfb776f27f0558e26eed43b5d9fe1b392",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
"reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"doctrine/coding-standard": "^11.0",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^8.5 || ^9.5",
"vimeo/psalm": "^4.25"
"vimeo/psalm": "^4.25 || ^5.4"
},
"time": "2022-09-07T09:01:28+00:00",
"time": "2023-06-16T13:40:37+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -137,7 +137,7 @@
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.0.5"
"source": "https://github.com/doctrine/inflector/tree/2.0.8"
},
"funding": [
{
@ -157,29 +157,29 @@
},
{
"name": "graham-campbell/result-type",
"version": "v1.1.0",
"version_normalized": "1.1.0.0",
"version": "v1.1.1",
"version_normalized": "1.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/GrahamCampbell/Result-Type.git",
"reference": "a878d45c1914464426dc94da61c9e1d36ae262a8"
"reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/a878d45c1914464426dc94da61c9e1d36ae262a8",
"reference": "a878d45c1914464426dc94da61c9e1d36ae262a8",
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831",
"reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"phpoption/phpoption": "^1.9"
"phpoption/phpoption": "^1.9.1"
},
"require-dev": {
"phpunit/phpunit": "^8.5.28 || ^9.5.21"
"phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12"
},
"time": "2022-07-30T15:56:11+00:00",
"time": "2023-02-25T20:23:15+00:00",
"type": "library",
"installation-source": "dist",
"installation-source": "source",
"autoload": {
"psr-4": {
"GrahamCampbell\\ResultType\\": "src/"
@ -206,7 +206,7 @@
],
"support": {
"issues": "https://github.com/GrahamCampbell/Result-Type/issues",
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.0"
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.1"
},
"funding": [
{
@ -282,17 +282,17 @@
},
{
"name": "monolog/monolog",
"version": "2.8.0",
"version_normalized": "2.8.0.0",
"version": "2.9.1",
"version_normalized": "2.9.1.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "720488632c590286b88b80e62aa3d3d551ad4a50"
"reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/720488632c590286b88b80e62aa3d3d551ad4a50",
"reference": "720488632c590286b88b80e62aa3d3d551ad4a50",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1",
"reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1",
"shasum": ""
},
"require": {
@ -307,7 +307,7 @@
"doctrine/couchdb": "~1.0@dev",
"elasticsearch/elasticsearch": "^7 || ^8",
"ext-json": "*",
"graylog2/gelf-php": "^1.4.2",
"graylog2/gelf-php": "^1.4.2 || ^2@dev",
"guzzlehttp/guzzle": "^7.4",
"guzzlehttp/psr7": "^2.2",
"mongodb/mongodb": "^1.8",
@ -338,7 +338,7 @@
"rollbar/rollbar": "Allow sending log messages to Rollbar",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server"
},
"time": "2022-07-24T11:55:47+00:00",
"time": "2023-02-06T13:44:46+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -371,7 +371,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
"source": "https://github.com/Seldaek/monolog/tree/2.8.0"
"source": "https://github.com/Seldaek/monolog/tree/2.9.1"
},
"funding": [
{
@ -446,27 +446,27 @@
},
{
"name": "phpoption/phpoption",
"version": "1.9.0",
"version_normalized": "1.9.0.0",
"version": "1.9.1",
"version_normalized": "1.9.1.0",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/php-option.git",
"reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab"
"reference": "dd3a383e599f49777d8b628dadbb90cae435b87e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dc5ff11e274a90cc1c743f66c9ad700ce50db9ab",
"reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab",
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e",
"reference": "dd3a383e599f49777d8b628dadbb90cae435b87e",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8",
"phpunit/phpunit": "^8.5.28 || ^9.5.21"
"bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12"
},
"time": "2022-07-30T15:51:26+00:00",
"time": "2023-02-25T19:38:58+00:00",
"type": "library",
"extra": {
"bamarni-bin": {
@ -508,7 +508,7 @@
],
"support": {
"issues": "https://github.com/schmittjoh/php-option/issues",
"source": "https://github.com/schmittjoh/php-option/tree/1.9.0"
"source": "https://github.com/schmittjoh/php-option/tree/1.9.1"
},
"funding": [
{
@ -645,17 +645,17 @@
},
{
"name": "rhilip/bencode",
"version": "v2.3.1",
"version_normalized": "2.3.1.0",
"version": "v2.3.3",
"version_normalized": "2.3.3.0",
"source": {
"type": "git",
"url": "https://github.com/Rhilip/Bencode.git",
"reference": "8ebf93f9213315407bbb91f6aa7d5e5f5efa3892"
"reference": "fd37d13bb745352d40879dbbfa6da85af91e49f1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Rhilip/Bencode/zipball/8ebf93f9213315407bbb91f6aa7d5e5f5efa3892",
"reference": "8ebf93f9213315407bbb91f6aa7d5e5f5efa3892",
"url": "https://api.github.com/repos/Rhilip/Bencode/zipball/fd37d13bb745352d40879dbbfa6da85af91e49f1",
"reference": "fd37d13bb745352d40879dbbfa6da85af91e49f1",
"shasum": ""
},
"require": {
@ -667,9 +667,9 @@
"suggest": {
"php-64bit": "Running 64 bit is recommended to prevent integer overflow"
},
"time": "2022-07-17T11:19:47+00:00",
"time": "2023-05-27T01:47:00+00:00",
"type": "library",
"installation-source": "dist",
"installation-source": "source",
"autoload": {
"psr-4": {
"Rhilip\\Bencode\\": "src"
@ -693,23 +693,23 @@
],
"support": {
"issues": "https://github.com/Rhilip/Bencode/issues",
"source": "https://github.com/Rhilip/Bencode/tree/v2.3.1"
"source": "https://github.com/Rhilip/Bencode/tree/v2.3.3"
},
"install-path": "../rhilip/bencode"
},
{
"name": "symfony/console",
"version": "v5.4.13",
"version_normalized": "5.4.13.0",
"version": "v5.4.26",
"version_normalized": "5.4.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be"
"reference": "b504a3d266ad2bb632f196c0936ef2af5ff6e273"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be",
"reference": "3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be",
"url": "https://api.github.com/repos/symfony/console/zipball/b504a3d266ad2bb632f196c0936ef2af5ff6e273",
"reference": "b504a3d266ad2bb632f196c0936ef2af5ff6e273",
"shasum": ""
},
"require": {
@ -747,9 +747,9 @@
"symfony/lock": "",
"symfony/process": ""
},
"time": "2022-08-26T13:50:20+00:00",
"time": "2023-07-19T20:11:33+00:00",
"type": "library",
"installation-source": "dist",
"installation-source": "source",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
@ -776,12 +776,12 @@
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command line",
"command-line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.4.13"
"source": "https://github.com/symfony/console/tree/v5.4.26"
},
"funding": [
{
@ -871,17 +871,17 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.26.0",
"version_normalized": "1.26.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
@ -893,11 +893,11 @@
"suggest": {
"ext-ctype": "For best performance"
},
"time": "2022-05-24T11:49:31+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -936,7 +936,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
@ -956,17 +956,17 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.26.0",
"version_normalized": "1.26.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
@ -975,11 +975,11 @@
"suggest": {
"ext-intl": "For best performance"
},
"time": "2022-05-24T11:49:31+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1020,7 +1020,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
@ -1040,17 +1040,17 @@
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.26.0",
"version_normalized": "1.26.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
@ -1059,11 +1059,11 @@
"suggest": {
"ext-intl": "For best performance"
},
"time": "2022-05-24T11:49:31+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1107,7 +1107,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
@ -1127,17 +1127,17 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.26.0",
"version_normalized": "1.26.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
@ -1149,11 +1149,11 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2022-05-24T11:49:31+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1193,7 +1193,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
@ -1213,34 +1213,34 @@
},
{
"name": "symfony/polyfill-php73",
"version": "v1.26.0",
"version_normalized": "1.26.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2022-05-24T11:49:31+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"installation-source": "dist",
"installation-source": "source",
"autoload": {
"files": [
"bootstrap.php"
@ -1275,7 +1275,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0"
},
"funding": [
{
@ -1295,34 +1295,34 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.26.0",
"version_normalized": "1.26.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2022-05-10T07:21:04+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"installation-source": "dist",
"installation-source": "source",
"autoload": {
"files": [
"bootstrap.php"
@ -1361,7 +1361,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
@ -1445,17 +1445,17 @@
},
{
"name": "symfony/string",
"version": "v5.4.13",
"version_normalized": "5.4.13.0",
"version": "v5.4.26",
"version_normalized": "5.4.26.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "2900c668a32138a34118740de3e4d5a701801f53"
"reference": "1181fe9270e373537475e826873b5867b863883c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/2900c668a32138a34118740de3e4d5a701801f53",
"reference": "2900c668a32138a34118740de3e4d5a701801f53",
"url": "https://api.github.com/repos/symfony/string/zipball/1181fe9270e373537475e826873b5867b863883c",
"reference": "1181fe9270e373537475e826873b5867b863883c",
"shasum": ""
},
"require": {
@ -1475,9 +1475,9 @@
"symfony/translation-contracts": "^1.1|^2",
"symfony/var-exporter": "^4.4|^5.0|^6.0"
},
"time": "2022-09-01T01:52:16+00:00",
"time": "2023-06-28T12:46:07+00:00",
"type": "library",
"installation-source": "dist",
"installation-source": "source",
"autoload": {
"files": [
"Resources/functions.php"
@ -1514,7 +1514,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.4.13"
"source": "https://github.com/symfony/string/tree/v5.4.26"
},
"funding": [
{
@ -1623,17 +1623,17 @@
},
{
"name": "webman/console",
"version": "v1.2.15",
"version_normalized": "1.2.15.0",
"version": "v1.2.37",
"version_normalized": "1.2.37.0",
"source": {
"type": "git",
"url": "https://github.com/webman-php/console.git",
"reference": "71932aa62427fbd95ef06178704576bc3274102d"
"reference": "c94d7f351ac09435825e1f84a67413cf5caa1a2a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webman-php/console/zipball/71932aa62427fbd95ef06178704576bc3274102d",
"reference": "71932aa62427fbd95ef06178704576bc3274102d",
"url": "https://api.github.com/repos/webman-php/console/zipball/c94d7f351ac09435825e1f84a67413cf5caa1a2a",
"reference": "c94d7f351ac09435825e1f84a67413cf5caa1a2a",
"shasum": ""
},
"require": {
@ -1643,9 +1643,9 @@
"require-dev": {
"workerman/webman": "^1.0"
},
"time": "2022-09-28T07:16:22+00:00",
"time": "2023-07-26T06:31:50+00:00",
"type": "library",
"installation-source": "dist",
"installation-source": "source",
"autoload": {
"psr-4": {
"Webman\\Console\\": "src"
@ -1679,22 +1679,22 @@
},
{
"name": "webman/event",
"version": "v1.0.2",
"version_normalized": "1.0.2.0",
"version": "v1.0.4",
"version_normalized": "1.0.4.0",
"source": {
"type": "git",
"url": "https://github.com/webman-php/event.git",
"reference": "db17d2fd6a5a8799f97f587b17a26b814901e01a"
"reference": "f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webman-php/event/zipball/db17d2fd6a5a8799f97f587b17a26b814901e01a",
"reference": "db17d2fd6a5a8799f97f587b17a26b814901e01a",
"url": "https://api.github.com/repos/webman-php/event/zipball/f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7",
"reference": "f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7",
"shasum": ""
},
"time": "2022-06-16T06:25:20+00:00",
"time": "2023-03-28T04:01:23+00:00",
"type": "library",
"installation-source": "dist",
"installation-source": "source",
"autoload": {
"psr-4": {
"Webman\\Event\\": "src"
@ -1707,30 +1707,30 @@
"description": "Webman event plugin",
"support": {
"issues": "https://github.com/webman-php/event/issues",
"source": "https://github.com/webman-php/event/tree/v1.0.2"
"source": "https://github.com/webman-php/event/tree/v1.0.4"
},
"install-path": "../webman/event"
},
{
"name": "workerman/crontab",
"version": "v1.0.4",
"version_normalized": "1.0.4.0",
"version": "v1.0.6",
"version_normalized": "1.0.6.0",
"source": {
"type": "git",
"url": "https://github.com/walkor/crontab.git",
"reference": "b9280b14941840d1b8542633d60ef303cefe3875"
"reference": "b78f1556f2977715b9cb5653129e6d9cf160d966"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/crontab/zipball/b9280b14941840d1b8542633d60ef303cefe3875",
"reference": "b9280b14941840d1b8542633d60ef303cefe3875",
"url": "https://api.github.com/repos/walkor/crontab/zipball/b78f1556f2977715b9cb5653129e6d9cf160d966",
"reference": "b78f1556f2977715b9cb5653129e6d9cf160d966",
"shasum": ""
},
"require": {
"php": ">=7.0",
"workerman/workerman": ">=4.0.20"
},
"time": "2022-08-01T10:24:22+00:00",
"time": "2022-10-17T01:59:19+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1766,29 +1766,30 @@
},
{
"name": "workerman/webman-framework",
"version": "v1.4.7",
"version_normalized": "1.4.7.0",
"version": "v1.5.8",
"version_normalized": "1.5.8.0",
"source": {
"type": "git",
"url": "https://github.com/walkor/webman-framework.git",
"reference": "e9815557f08dffd3a41b54f709a98619aab84f16"
"reference": "1cf2d1c8231dd4acaf88a491170552747f325732"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/webman-framework/zipball/e9815557f08dffd3a41b54f709a98619aab84f16",
"reference": "e9815557f08dffd3a41b54f709a98619aab84f16",
"url": "https://api.github.com/repos/walkor/webman-framework/zipball/1cf2d1c8231dd4acaf88a491170552747f325732",
"reference": "1cf2d1c8231dd4acaf88a491170552747f325732",
"shasum": ""
},
"require": {
"ext-json": "*",
"nikic/fast-route": "^1.3",
"php": ">=7.2",
"psr/container": ">=1.0",
"workerman/workerman": "^4.0.4"
"workerman/workerman": "^4.0.4 || ^5.0.0"
},
"suggest": {
"ext-event": "For better performance. "
},
"time": "2022-09-19T08:03:06+00:00",
"time": "2023-07-21T09:39:36+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1826,31 +1827,21 @@
"source": "https://github.com/walkor/webman-framework",
"wiki": "https://doc.workerman.net/"
},
"funding": [
{
"url": "https://opencollective.com/walkor",
"type": "open_collective"
},
{
"url": "https://www.patreon.com/walkor",
"type": "patreon"
}
],
"install-path": "../workerman/webman-framework"
},
{
"name": "workerman/workerman",
"version": "v4.1.3",
"version_normalized": "4.1.3.0",
"version": "v4.1.13",
"version_normalized": "4.1.13.0",
"source": {
"type": "git",
"url": "https://github.com/walkor/workerman.git",
"reference": "01028d8008c5691ec38c5f675fc13d76496a6db9"
"reference": "807780ff672775fcd08f89e573a2824e939021ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/workerman/zipball/01028d8008c5691ec38c5f675fc13d76496a6db9",
"reference": "01028d8008c5691ec38c5f675fc13d76496a6db9",
"url": "https://api.github.com/repos/walkor/workerman/zipball/807780ff672775fcd08f89e573a2824e939021ce",
"reference": "807780ff672775fcd08f89e573a2824e939021ce",
"shasum": ""
},
"require": {
@ -1859,9 +1850,9 @@
"suggest": {
"ext-event": "For better performance. "
},
"time": "2022-09-23T14:05:12+00:00",
"time": "2023-07-31T05:57:25+00:00",
"type": "library",
"installation-source": "dist",
"installation-source": "source",
"autoload": {
"psr-4": {
"Workerman\\": "./"

View File

@ -1,267 +1,266 @@
<?php return array (
'root' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
<?php return array(
'root' => array(
'name' => 'workerman/webman',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '3c992d062b3d5df702892eb49db05c44dedfb49e',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev' => true,
),
'reference' => '24a29479103cbe2c1113b929790d619e99d20d03',
'name' => 'workerman/webman',
),
'versions' =>
array (
'curl/curl' =>
array (
'pretty_version' => '2.4.0',
'version' => '2.4.0.0',
'aliases' =>
array (
),
'reference' => 'ba385e40c5907850c555db24505c127fe29f1e44',
'versions' => array(
'curl/curl' => array(
'pretty_version' => '2.5.0',
'version' => '2.5.0.0',
'reference' => 'c4f8799c471e43b7c782c77d5c6e178d0465e210',
'type' => 'library',
'install_path' => __DIR__ . '/../curl/curl',
'aliases' => array(),
'dev_requirement' => false,
),
'doctrine/inflector' => array(
'pretty_version' => '2.0.8',
'version' => '2.0.8.0',
'reference' => 'f9301a5b2fb1216b2b08f02ba04dc45423db6bff',
'type' => 'library',
'install_path' => __DIR__ . '/../doctrine/inflector',
'aliases' => array(),
'dev_requirement' => false,
),
'graham-campbell/result-type' => array(
'pretty_version' => 'v1.1.1',
'version' => '1.1.1.0',
'reference' => '672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831',
'type' => 'library',
'install_path' => __DIR__ . '/../graham-campbell/result-type',
'aliases' => array(),
'dev_requirement' => false,
),
'ledccn/bittorrentclient' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '9aead6a8750befb518adec30dd27dc92d3ec88fa',
'type' => 'library',
'install_path' => __DIR__ . '/../ledccn/bittorrentclient',
'aliases' => array(
0 => '9999999-dev',
),
'dev_requirement' => false,
),
'monolog/monolog' => array(
'pretty_version' => '2.9.1',
'version' => '2.9.1.0',
'reference' => 'f259e2b15fb95494c83f52d3caad003bbf5ffaa1',
'type' => 'library',
'install_path' => __DIR__ . '/../monolog/monolog',
'aliases' => array(),
'dev_requirement' => false,
),
'nikic/fast-route' => array(
'pretty_version' => 'v1.3.0',
'version' => '1.3.0.0',
'reference' => '181d480e08d9476e61381e04a71b34dc0432e812',
'type' => 'library',
'install_path' => __DIR__ . '/../nikic/fast-route',
'aliases' => array(),
'dev_requirement' => false,
),
'phpoption/phpoption' => array(
'pretty_version' => '1.9.1',
'version' => '1.9.1.0',
'reference' => 'dd3a383e599f49777d8b628dadbb90cae435b87e',
'type' => 'library',
'install_path' => __DIR__ . '/../phpoption/phpoption',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/container' => array(
'pretty_version' => '2.0.2',
'version' => '2.0.2.0',
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/container',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/log' => array(
'pretty_version' => '1.1.4',
'version' => '1.1.4.0',
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/log',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/log-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '1.0|2.0',
1 => '1.0.0 || 2.0.0 || 3.0.0',
),
),
'rhilip/bencode' => array(
'pretty_version' => 'v2.3.3',
'version' => '2.3.3.0',
'reference' => 'fd37d13bb745352d40879dbbfa6da85af91e49f1',
'type' => 'library',
'install_path' => __DIR__ . '/../rhilip/bencode',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/console' => array(
'pretty_version' => 'v5.4.26',
'version' => '5.4.26.0',
'reference' => 'b504a3d266ad2bb632f196c0936ef2af5ff6e273',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/console',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/deprecation-contracts' => array(
'pretty_version' => 'v2.5.2',
'version' => '2.5.2.0',
'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '5bbc823adecdae860bb64756d639ecfec17b050a',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-intl-grapheme' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '511a08c03c1960e08a883f4cffcacd219b758354',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-intl-normalizer' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '19bd1e4fcd5b91116f14d8533c57831ed00571b6',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-php73' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '9e8ecb5f92152187c4799efd3c96b78ccab18ff9',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php73',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/service-contracts' => array(
'pretty_version' => 'v1.1.2',
'version' => '1.1.2.0',
'reference' => '191afdcb5804db960d26d8566b7e9a2843cab3a0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/service-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/string' => array(
'pretty_version' => 'v5.4.26',
'version' => '5.4.26.0',
'reference' => '1181fe9270e373537475e826873b5867b863883c',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/string',
'aliases' => array(),
'dev_requirement' => false,
),
'vlucas/phpdotenv' => array(
'pretty_version' => 'v5.1.0',
'version' => '5.1.0.0',
'reference' => '448c76d7a9e30c341ff5bc367a923af74ae18467',
'type' => 'library',
'install_path' => __DIR__ . '/../vlucas/phpdotenv',
'aliases' => array(),
'dev_requirement' => false,
),
'webman/console' => array(
'pretty_version' => 'v1.2.37',
'version' => '1.2.37.0',
'reference' => 'c94d7f351ac09435825e1f84a67413cf5caa1a2a',
'type' => 'library',
'install_path' => __DIR__ . '/../webman/console',
'aliases' => array(),
'dev_requirement' => false,
),
'webman/event' => array(
'pretty_version' => 'v1.0.4',
'version' => '1.0.4.0',
'reference' => 'f4478941c3b7efa4d7e9c063f2f6efd7ee3071a7',
'type' => 'library',
'install_path' => __DIR__ . '/../webman/event',
'aliases' => array(),
'dev_requirement' => false,
),
'workerman/crontab' => array(
'pretty_version' => 'v1.0.6',
'version' => '1.0.6.0',
'reference' => 'b78f1556f2977715b9cb5653129e6d9cf160d966',
'type' => 'library',
'install_path' => __DIR__ . '/../workerman/crontab',
'aliases' => array(),
'dev_requirement' => false,
),
'workerman/webman' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '3c992d062b3d5df702892eb49db05c44dedfb49e',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev_requirement' => false,
),
'workerman/webman-framework' => array(
'pretty_version' => 'v1.5.8',
'version' => '1.5.8.0',
'reference' => '1cf2d1c8231dd4acaf88a491170552747f325732',
'type' => 'library',
'install_path' => __DIR__ . '/../workerman/webman-framework',
'aliases' => array(),
'dev_requirement' => false,
),
'workerman/workerman' => array(
'pretty_version' => 'v4.1.13',
'version' => '4.1.13.0',
'reference' => '807780ff672775fcd08f89e573a2824e939021ce',
'type' => 'library',
'install_path' => __DIR__ . '/../workerman/workerman',
'aliases' => array(),
'dev_requirement' => false,
),
),
'doctrine/inflector' =>
array (
'pretty_version' => '2.0.5',
'version' => '2.0.5.0',
'aliases' =>
array (
),
'reference' => 'ade2b3bbfb776f27f0558e26eed43b5d9fe1b392',
),
'graham-campbell/result-type' =>
array (
'pretty_version' => 'v1.1.0',
'version' => '1.1.0.0',
'aliases' =>
array (
),
'reference' => 'a878d45c1914464426dc94da61c9e1d36ae262a8',
),
'ledccn/bittorrentclient' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
0 => '9999999-dev',
),
'reference' => '9aead6a8750befb518adec30dd27dc92d3ec88fa',
),
'monolog/monolog' =>
array (
'pretty_version' => '2.8.0',
'version' => '2.8.0.0',
'aliases' =>
array (
),
'reference' => '720488632c590286b88b80e62aa3d3d551ad4a50',
),
'nikic/fast-route' =>
array (
'pretty_version' => 'v1.3.0',
'version' => '1.3.0.0',
'aliases' =>
array (
),
'reference' => '181d480e08d9476e61381e04a71b34dc0432e812',
),
'phpoption/phpoption' =>
array (
'pretty_version' => '1.9.0',
'version' => '1.9.0.0',
'aliases' =>
array (
),
'reference' => 'dc5ff11e274a90cc1c743f66c9ad700ce50db9ab',
),
'psr/container' =>
array (
'pretty_version' => '2.0.2',
'version' => '2.0.2.0',
'aliases' =>
array (
),
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
),
'psr/log' =>
array (
'pretty_version' => '1.1.4',
'version' => '1.1.4.0',
'aliases' =>
array (
),
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
),
'psr/log-implementation' =>
array (
'provided' =>
array (
0 => '1.0.0 || 2.0.0 || 3.0.0',
1 => '1.0|2.0',
),
),
'rhilip/bencode' =>
array (
'pretty_version' => 'v2.3.1',
'version' => '2.3.1.0',
'aliases' =>
array (
),
'reference' => '8ebf93f9213315407bbb91f6aa7d5e5f5efa3892',
),
'symfony/console' =>
array (
'pretty_version' => 'v5.4.13',
'version' => '5.4.13.0',
'aliases' =>
array (
),
'reference' => '3f97f6c7b7e26848a90c0c0cfb91eeb2bb8618be',
),
'symfony/deprecation-contracts' =>
array (
'pretty_version' => 'v2.5.2',
'version' => '2.5.2.0',
'aliases' =>
array (
),
'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
),
'symfony/polyfill-ctype' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => '6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4',
),
'symfony/polyfill-intl-grapheme' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => '433d05519ce6990bf3530fba6957499d327395c2',
),
'symfony/polyfill-intl-normalizer' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => '219aa369ceff116e673852dce47c3a41794c14bd',
),
'symfony/polyfill-mbstring' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => '9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e',
),
'symfony/polyfill-php73' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => 'e440d35fa0286f77fb45b79a03fedbeda9307e85',
),
'symfony/polyfill-php80' =>
array (
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'aliases' =>
array (
),
'reference' => 'cfa0ae98841b9e461207c13ab093d76b0fa7bace',
),
'symfony/service-contracts' =>
array (
'pretty_version' => 'v1.1.2',
'version' => '1.1.2.0',
'aliases' =>
array (
),
'reference' => '191afdcb5804db960d26d8566b7e9a2843cab3a0',
),
'symfony/string' =>
array (
'pretty_version' => 'v5.4.13',
'version' => '5.4.13.0',
'aliases' =>
array (
),
'reference' => '2900c668a32138a34118740de3e4d5a701801f53',
),
'vlucas/phpdotenv' =>
array (
'pretty_version' => 'v5.1.0',
'version' => '5.1.0.0',
'aliases' =>
array (
),
'reference' => '448c76d7a9e30c341ff5bc367a923af74ae18467',
),
'webman/console' =>
array (
'pretty_version' => 'v1.2.15',
'version' => '1.2.15.0',
'aliases' =>
array (
),
'reference' => '71932aa62427fbd95ef06178704576bc3274102d',
),
'webman/event' =>
array (
'pretty_version' => 'v1.0.2',
'version' => '1.0.2.0',
'aliases' =>
array (
),
'reference' => 'db17d2fd6a5a8799f97f587b17a26b814901e01a',
),
'workerman/crontab' =>
array (
'pretty_version' => 'v1.0.4',
'version' => '1.0.4.0',
'aliases' =>
array (
),
'reference' => 'b9280b14941840d1b8542633d60ef303cefe3875',
),
'workerman/webman' =>
array (
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'aliases' =>
array (
),
'reference' => '24a29479103cbe2c1113b929790d619e99d20d03',
),
'workerman/webman-framework' =>
array (
'pretty_version' => 'v1.4.7',
'version' => '1.4.7.0',
'aliases' =>
array (
),
'reference' => 'e9815557f08dffd3a41b54f709a98619aab84f16',
),
'workerman/workerman' =>
array (
'pretty_version' => 'v4.1.3',
'version' => '4.1.3.0',
'aliases' =>
array (
),
'reference' => '01028d8008c5691ec38c5f675fc13d76496a6db9',
),
),
);

26
vendor/composer/platform_check.php vendored Normal file
View File

@ -0,0 +1,26 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 70400)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

15
vendor/curl/curl/.php-cs-fixer.dist.php vendored Normal file
View File

@ -0,0 +1,15 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__)
;
$config = new PhpCsFixer\Config();
return $config->setRules([
'@PSR12' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'no_unused_imports' => true,
'visibility_required' => ['elements' => ['property', 'method']]
])
->setFinder($finder)
;

View File

@ -2,6 +2,14 @@
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
## 2.5.0 (14. December 2022)
+ [#95](https://github.com/php-mod/curl/issues/95) Potential memory leak prevention where curl object was not destroyed due to object reference.
+ [#94](https://github.com/php-mod/curl/pull/94) Added method to retrieve all curl options from current object.
+ [#93](https://github.com/php-mod/curl/pull/93) Text and Coding Standards update.
+ [#97](https://github.com/php-mod/curl/pull/97) Added Unit Testing for PHP 8.2.
+ [#99](https://github.com/php-mod/curl/pull/99) Added PHPStan testing to GitHub Actions and fixed errors from testing with PHPStan.
## 2.4.0 (29. August 2022)
+ [#84](https://github.com/php-mod/curl/pull/84) Added `.gitattributes`.

View File

@ -1,6 +1,6 @@
# PHP Curl Class
This library provides an object-oriented wrapper of the PHP cURL extension.
This library provides an object-oriented and dependency free wrapper of the PHP cURL extension.
[![Maintainability](https://api.codeclimate.com/v1/badges/6c34bb31f3eb6df36c7d/maintainability)](https://codeclimate.com/github/php-mod/curl/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/6c34bb31f3eb6df36c7d/test_coverage)](https://codeclimate.com/github/php-mod/curl/test_coverage)
@ -9,8 +9,6 @@ This library provides an object-oriented wrapper of the PHP cURL extension.
If you have questions or problems with installation or usage [create an Issue](https://github.com/php-mod/curl/issues).
## Installation
In order to install this library via composer run the following command in the console:
@ -27,39 +25,49 @@ or add the package manually to your composer.json file in the require section:
## Usage examples
```php
$curl = new Curl\Curl();
$curl->get('http://www.example.com/');
```
A few example for using CURL with get:
```php
$curl = new Curl\Curl();
$curl->get('http://www.example.com/search', array(
$curl = (new Curl\Curl())->get('http://www.example.com/');
if ($curl->isSuccess()) {
// do something with response
var_dump($curl->response);
}
// ensure to close the curl connection
$curl->close();
```
Or with params, values will be encoded with `PHP_QUERY_RFC1738`:
```php
$curl = (new Curl\Curl())->get('http://www.example.com/search', [
'q' => 'keyword',
));
]);
```
An example using post
```php
$curl = new Curl\Curl();
$curl->post('http://www.example.com/login/', array(
$curl->post('http://www.example.com/login/', [
'username' => 'myusername',
'password' => 'mypassword',
));
]);
```
An exampling using basic authentication, remove default user agent and working with error handling
```php
$curl = new Curl\Curl();
$curl->setBasicAuthentication('username', 'password');
$curl->setUserAgent('');
$curl->setReferrer('');
$curl->setHeader('X-Requested-With', 'XMLHttpRequest');
$curl->setCookie('key', 'value');
$curl->get('http://www.example.com/');
if ($curl->error) {
echo $curl->error_code;
}
else {
} else {
echo $curl->response;
}
@ -67,6 +75,8 @@ var_dump($curl->request_headers);
var_dump($curl->response_headers);
```
SSL verification setup:
```php
$curl = new Curl\Curl();
$curl->setOpt(CURLOPT_RETURNTRANSFER, TRUE);
@ -74,40 +84,16 @@ $curl->setOpt(CURLOPT_SSL_VERIFYPEER, FALSE);
$curl->get('https://encrypted.example.com/');
```
```php
$curl = new Curl\Curl();
$curl->put('http://api.example.com/user/', array(
'first_name' => 'Zach',
'last_name' => 'Borboa',
));
```
Example access to curl object:
```php
$curl = new Curl\Curl();
$curl->patch('http://api.example.com/profile/', array(
'image' => '@path/to/file.jpg',
));
```
```php
$curl = new Curl\Curl();
$curl->delete('http://api.example.com/user/', array(
'id' => '1234',
));
```
```php
$curl->close();
```
```php
// Example access to curl object.
curl_set_opt($curl->curl, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1');
curl_close($curl->curl);
```
Example of downloading a file or any other content
```php
// Example of downloading a file or any other content
$curl = new Curl\Curl();
// open the file where the request response should be written
$file_handle = fopen($target_file, 'w+');
@ -121,7 +107,6 @@ $curl->setOpt(CURLOPT_FILE, null);
fclose($file_handle);
```
## Testing
In order to test the library:
@ -130,4 +115,4 @@ In order to test the library:
2. Clone the fork to your machine
3. Install the depencies `composer install`
4. Build and start the docker image (in `tests/server`) `docker build . -t curlserver` start `docker run -p 1234:80 curlserver`
4. Run the unit tests `./vendor/bin/phpunit tests`
5. Run the unit tests `./vendor/bin/phpunit tests`

View File

@ -1,7 +1,10 @@
{
"name": "curl/curl",
"description": "cURL class for PHP",
"keywords": ["dot", "curl"],
"keywords": [
"dot",
"curl"
],
"homepage": "https://github.com/php-mod/curl",
"type": "library",
"license": "MIT",
@ -31,5 +34,8 @@
"psr-0": {
"Curl": "src/"
}
},
"scripts": {
"phpstan": "./phpstan.phar -v"
}
}
}

View File

@ -34,39 +34,39 @@ class Curl
// The HTTP authentication method(s) to use.
/**
* @var string Type AUTH_BASIC
* @var int Type AUTH_BASIC
*/
const AUTH_BASIC = CURLAUTH_BASIC;
/**
* @var string Type AUTH_DIGEST
* @var int Type AUTH_DIGEST
*/
const AUTH_DIGEST = CURLAUTH_DIGEST;
/**
* @var string Type AUTH_GSSNEGOTIATE
* @var int Type AUTH_GSSNEGOTIATE
*/
const AUTH_GSSNEGOTIATE = CURLAUTH_GSSNEGOTIATE;
/**
* @var string Type AUTH_NTLM
* @var int Type AUTH_NTLM
*/
const AUTH_NTLM = CURLAUTH_NTLM;
/**
* @var string Type AUTH_ANY
* @var int Type AUTH_ANY
*/
const AUTH_ANY = CURLAUTH_ANY;
/**
* @var string Type AUTH_ANYSAFE
* @var int Type AUTH_ANYSAFE
*/
const AUTH_ANYSAFE = CURLAUTH_ANYSAFE;
/**
* @var string The user agent name which is set when making a request
*/
const USER_AGENT = 'PHP Curl/2.3 (+https://github.com/php-mod/curl)';
const USER_AGENT = 'PHP Curl/2.5 (+https://github.com/php-mod/curl)';
private $_cookies = array();
@ -172,7 +172,7 @@ class Curl
$this->setOpt(CURLINFO_HEADER_OUT, true);
$this->setOpt(CURLOPT_HEADER, false);
$this->setOpt(CURLOPT_RETURNTRANSFER, true);
$this->setOpt(CURLOPT_HEADERFUNCTION, array($this, 'addResponseHeaderLine'));
return $this;
}
@ -195,7 +195,7 @@ class Curl
} elseif (!$this->response_header_continue) {
$this->response_headers[] = $trimmed_header;
}
return strlen($header_line);
}
@ -208,6 +208,7 @@ class Curl
*/
public function exec()
{
$this->setOpt(CURLOPT_HEADERFUNCTION, array($this, 'addResponseHeaderLine'));
$this->response_headers = array();
$this->response = curl_exec($this->curl);
$this->curl_error_code = curl_errno($this->curl);
@ -220,7 +221,7 @@ class Curl
$this->request_headers = preg_split('/\r\n/', curl_getinfo($this->curl, CURLINFO_HEADER_OUT), -1, PREG_SPLIT_NO_EMPTY);
$this->http_error_message = $this->error ? (isset($this->response_headers['0']) ? $this->response_headers['0'] : '') : '';
$this->error_message = $this->curl_error ? $this->getErrorMessage() : $this->http_error_message;
$this->setOpt(CURLOPT_HEADERFUNCTION, null);
return $this->error_code;
}
@ -241,7 +242,7 @@ class Curl
$skip = true;
}
}
if (!$skip) {
$data = http_build_query($data);
}
@ -284,7 +285,7 @@ class Curl
// public methods
/**
* @deprecated use `exec()` directly.
* @deprecated use `exec()` directly. Will be removed in 3.0
*/
public function _exec()
{
@ -318,25 +319,25 @@ class Curl
/**
* Purge Request
*
* A very common scenario to send a purge request is within the use of varnish, therefore
* A very common scenario to send a purge request is within the use of varnish, therefore
* the optional hostname can be defined.
*
* @param strng $url The url to make the purge request
* @param string $hostname An optional hostname which will be sent as http host header
*
* @param string $url The url to make the purge request
* @param string $hostName An optional hostname which will be sent as http host header
* @return self
* @since 2.4.0
*/
public function purge($url, $hostName = null)
{
$this->setOpt(CURLOPT_URL, $url);
$this->setOpt(CURLOPT_CUSTOMREQUEST, 'PURGE');
$this->setOpt(CURLOPT_CUSTOMREQUEST, 'PURGE');
if ($hostName) {
$this->setHeader('Host', $hostName);
}
$this->exec();
return $this;
}
/**
* Make a post request with optional post data.
*
@ -511,7 +512,7 @@ class Curl
}
/**
* @deprecated Call setReferer() instead
* @deprecated Call setReferer() instead. Will be removed in 3.0
*
* @param $referrer
* @return self
@ -556,7 +557,6 @@ class Curl
* To see a full list of options: http://php.net/curl_setopt
*
* @see http://php.net/curl_setopt
*
* @param int $option The curl option constant e.g. `CURLOPT_AUTOREFERER`, `CURLOPT_COOKIESESSION`
* @param mixed $value The value to pass for the given $option
* @return bool
@ -567,26 +567,37 @@ class Curl
}
/**
* Get customized curl options.
* Get curl option for a certain name
*
* To see a full list of options: http://php.net/curl_getinfo
*
* @see http://php.net/curl_getinfo
*
* @param int $option The curl option constant e.g. `CURLOPT_AUTOREFERER`, `CURLOPT_COOKIESESSION`
* @param mixed The value to check for the given $option
* @return mixed
*/
public function getOpt($option)
{
return curl_getinfo($this->curl, $option);
}
/**
* Return the all options for current curl ressource
*
* To see a full list of options: http://php.net/curl_getinfo
*
* @see http://php.net/curl_getinfo
* @return array
* @since 2.5.0
*/
public function getOpts()
{
return curl_getinfo($this->curl);
}
/**
* Return the endpoint set for curl
*
* @see http://php.net/curl_getinfo
*
* @return string of endpoint
*/
public function getEndpoint()
@ -607,7 +618,7 @@ class Curl
}
/**
* @deprecated Call setVerbose() instead
* @deprecated Call setVerbose() instead. Will be removed in 3.0
*
* @param bool $on
* @return self
@ -717,7 +728,7 @@ class Curl
{
return $this->getHttpStatus() >= 500 && $this->getHttpStatus() < 600;
}
/**
* Get a specific response header key or all values from the response headers array.
*
@ -750,17 +761,17 @@ class Curl
foreach ($this->response_headers as $header) {
$parts = explode(":", $header, 2);
$key = isset($parts[0]) ? $parts[0] : '';
$value = isset($parts[1]) ? $parts[1] : '';
$headers[trim(strtolower($key))] = trim($value);
}
if ($headerKey) {
return isset($headers[$headerKey]) ? $headers[$headerKey] : false;
}
return $headers;
}
@ -775,7 +786,7 @@ class Curl
/**
* Get curl error code
* @return string
* @return int
*/
public function getErrorCode()
{

View File

@ -16,12 +16,12 @@
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"doctrine/coding-standard": "^11.0",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^8.5 || ^9.5",
"vimeo/psalm": "^4.25"
"vimeo/psalm": "^4.25 || ^5.4"
},
"autoload": {
"psr-4": {

View File

@ -11,9 +11,7 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('(s)tatuses$'), '\1\2tatus');
@ -61,9 +59,7 @@ class Inflectible
yield new Transformation(new Pattern('s$'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatuses');
@ -93,9 +89,7 @@ class Inflectible
yield new Transformation(new Pattern('$'), 's');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('atlas'), new Word('atlases'));
@ -104,6 +98,7 @@ class Inflectible
yield new Substitution(new Word('blouse'), new Word('blouses'));
yield new Substitution(new Word('brother'), new Word('brothers'));
yield new Substitution(new Word('cafe'), new Word('cafes'));
yield new Substitution(new Word('cave'), new Word('caves'));
yield new Substitution(new Word('chateau'), new Word('chateaux'));
yield new Substitution(new Word('niveau'), new Word('niveaux'));
yield new Substitution(new Word('child'), new Word('children'));
@ -154,6 +149,7 @@ class Inflectible
yield new Substitution(new Word('runner-up'), new Word('runners-up'));
yield new Substitution(new Word('safe'), new Word('safes'));
yield new Substitution(new Word('sex'), new Word('sexes'));
yield new Substitution(new Word('sieve'), new Word('sieves'));
yield new Substitution(new Word('soliloquy'), new Word('soliloquies'));
yield new Substitution(new Word('son-in-law'), new Word('sons-in-law'));
yield new Substitution(new Word('syllabus'), new Word('syllabi'));

View File

@ -8,9 +8,7 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
@ -30,9 +28,7 @@ final class Uninflected
yield new Pattern('utopia');
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
@ -43,9 +39,7 @@ final class Uninflected
yield new Pattern('media');
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('\w+media');

View File

@ -11,9 +11,7 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/'), '\1ail');
@ -23,9 +21,7 @@ class Inflectible
yield new Transformation(new Pattern('/s$/'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/(s|x|z)$/'), '\1');
@ -38,9 +34,7 @@ class Inflectible
yield new Transformation(new Pattern('/$/'), 's');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('monsieur'), new Word('messieurs'));

View File

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('');

View File

@ -11,18 +11,14 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/re$/i'), 'r');
yield new Transformation(new Pattern('/er$/i'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/e$/i'), 'er');
@ -30,9 +26,7 @@ class Inflectible
yield new Transformation(new Pattern('/$/'), 'er');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('konto'), new Word('konti'));

View File

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('barn');

View File

@ -11,9 +11,7 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/^(g|)ases$/i'), '\1ás');
@ -34,9 +32,7 @@ class Inflectible
yield new Transformation(new Pattern('/([^ê])s$/i'), '\1');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/^(alem|c|p)ao$/i'), '\1aes');
@ -58,9 +54,7 @@ class Inflectible
yield new Transformation(new Pattern('/$/'), 's');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('abdomen'), new Word('abdomens'));

View File

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('tórax');

View File

@ -11,9 +11,7 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/ereses$/'), 'erés');
@ -23,9 +21,7 @@ class Inflectible
yield new Transformation(new Pattern('/s$/'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/ú([sn])$/i'), 'u\1es');
@ -39,9 +35,7 @@ class Inflectible
yield new Transformation(new Pattern('/$/'), 's');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('el'), new Word('los'));

View File

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('lunes');

View File

@ -11,26 +11,20 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/l[ae]r$/i'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/([eöiü][^aoıueöiü]{0,6})$/u'), '\1ler');
yield new Transformation(new Pattern('/([aoıu][^aoıueöiü]{0,6})$/u'), '\1lar');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('ben'), new Word('biz'));

View File

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('lunes');

View File

@ -0,0 +1,9 @@
* text=auto
/tests export-ignore
/.gitattributes export-ignore
/.github export-ignore
/.gitignore export-ignore
/phpunit.xml.dist export-ignore
/CHANGELOG.md export-ignore
/README.md export-ignore

View File

@ -0,0 +1,132 @@
# CONTRIBUTOR COVENANT CODE OF CONDUCT
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
hello@gjcampbell.co.uk.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@ -0,0 +1,31 @@
# CONTRIBUTION GUIDELINES
Contributions are **welcome** and will be fully **credited**.
We accept contributions via pull requests on GitHub. Please review these guidelines before continuing.
## Guidelines
* Please follow the [PSR-12 Coding Style Guide](https://www.php-fig.org/psr/psr-12/), enforced by [StyleCI](https://styleci.io/).
* Ensure that the current tests pass, and if you've added something new, add the tests where relevant.
* Send a coherent commit history, making sure each commit in your pull request is meaningful.
* You may need to [rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) to avoid merge conflicts.
* If you are changing or adding to the behaviour or public API, you may need to update the docs.
* Please remember that we follow [Semantic Versioning](https://semver.org/).
## Running Tests
First, install the dependencies using [Composer](https://getcomposer.org/):
```bash
$ composer install
```
Then run [PHPUnit](https://phpunit.de/):
```bash
$ vendor/bin/phpunit
```
* The tests will be automatically run by [GitHub Actions](https://github.com/features/actions) against pull requests.
* We also have [StyleCI](https://styleci.io/) set up to automatically fix any code style issues.

View File

@ -0,0 +1,2 @@
github: GrahamCampbell
tidelift: "packagist/graham-campbell/result-type"

View File

@ -0,0 +1,14 @@
# SECURITY POLICY
## Supported Versions
After each new major release, the previous release will be supported for no
less than 2 years, unless explictly stated otherwise. This may mean that there
are multiple supported versions at any given time.
## Reporting a Vulnerability
If you discover a security vulnerability within this package, please send an
email to security@tidelift.com. All security vulnerabilities will be promptly
addressed. Please do not disclose security-related issues publicly until a fix
has been announced.

View File

@ -0,0 +1,40 @@
name: Tests
on:
push:
pull_request:
jobs:
tests:
name: PHP ${{ matrix.php }}
runs-on: ubuntu-22.04
strategy:
matrix:
php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2']
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2
coverage: none
env:
update: true
- name: Setup Problem Matchers
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Install PHP Dependencies
uses: nick-invision/retry@v2
with:
timeout_minutes: 5
max_attempts: 5
command: composer update --no-interaction --no-progress
- name: Execute PHPUnit
run: vendor/bin/phpunit

View File

@ -0,0 +1,4 @@
.phpunit.result.cache
composer.lock
phpunit.xml
vendor

View File

@ -0,0 +1,38 @@
CHANGE LOG
==========
## V1.1.1 (25/02/2023)
* Cleaned up tests
## V1.1 (30/07/2022)
* Added support for PHP 8.2
* Dropped support for PHP <7.2.5
## V1.0.4 (21/11/2021)
* Updated package metadata
## V1.0.3 (17/10/2021)
* Corrected docs
## V1.0.2 (28/08/2021)
* Added support for PHP 8.1
## V1.0.1 (13/04/2020)
* Updated funding information
## V1.0 (21/03/2020)
* Initial release

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2020-2022 Graham Campbell <hello@gjcampbell.co.uk>
Copyright (c) 2020-2023 Graham Campbell <hello@gjcampbell.co.uk>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -0,0 +1,42 @@
Result Type
===========
Result Type was created by, and is maintained by [Graham Campbell](https://github.com/GrahamCampbell), and is an implementation of the result type. Feel free to check out the [change log](CHANGELOG.md), [releases](https://github.com/GrahamCampbell/Result-Type/releases), [security policy](https://github.com/GrahamCampbell/Result-Type/security/policy), [license](LICENSE), [code of conduct](.github/CODE_OF_CONDUCT.md), and [contribution guidelines](.github/CONTRIBUTING.md).
![Banner](https://user-images.githubusercontent.com/2829600/77233209-f86aae80-6b9d-11ea-9cef-81501c9e858d.png)
<p align="center">
<a href="https://github.com/GrahamCampbell/Result-Type/actions?query=workflow%3ATests"><img src="https://img.shields.io/github/actions/workflow/status/GrahamCampbell/Result-Type/tests.yml?label=Tests&style=flat-square" alt="Build Status"></img></a>
<a href="https://github.styleci.io/repos/249026522"><img src="https://github.styleci.io/repos/249026522/shield" alt="StyleCI Status"></img></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-brightgreen?style=flat-square" alt="Software License"></img></a>
<a href="https://packagist.org/packages/graham-campbell/result-type"><img src="https://img.shields.io/packagist/dt/graham-campbell/result-type?style=flat-square" alt="Packagist Downloads"></img></a>
<a href="https://github.com/GrahamCampbell/Result-Type/releases"><img src="https://img.shields.io/github/release/GrahamCampbell/Result-Type?style=flat-square" alt="Latest Version"></img></a>
</p>
## Installation
This version requires [PHP](https://www.php.net/) 7.2.5-8.2.
To get the latest version, simply require the project using [Composer](https://getcomposer.org/):
```bash
$ composer require "graham-campbell/result-type:^1.1"
```
## Security
If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. You may view our full security policy [here](https://github.com/GrahamCampbell/Result-Type/security/policy).
## License
Result Type is licensed under [The MIT License (MIT)](LICENSE).
## For Enterprise
Available as part of the Tidelift Subscription
The maintainers of `graham-campbell/result-type` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-graham-campbell-result-type?utm_source=packagist-graham-campbell-result-type&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)

View File

@ -12,10 +12,10 @@
],
"require": {
"php": "^7.2.5 || ^8.0",
"phpoption/phpoption": "^1.9"
"phpoption/phpoption": "^1.9.1"
},
"require-dev": {
"phpunit/phpunit": "^8.5.28 || ^9.5.21"
"phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12"
},
"autoload": {
"psr-4": {

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" beStrictAboutTestsThatDoNotTestAnything="true" beStrictAboutOutputDuringTests="true" bootstrap="vendor/autoload.php" colors="true" failOnRisky="true" failOnWarning="true" processIsolation="false" stopOnError="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd">
<testsuites>
<testsuite name="Result Type Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">./src</directory>
</include>
</coverage>
</phpunit>

View File

@ -0,0 +1,95 @@
<?php
declare(strict_types=1);
/*
* This file is part of Result Type.
*
* (c) Graham Campbell <hello@gjcampbell.co.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace GrahamCampbell\Tests\ResultType;
use GrahamCampbell\ResultType\Error;
use GrahamCampbell\ResultType\Success;
use PHPUnit\Framework\TestCase;
use RuntimeException;
class ResultTest extends TestCase
{
public function testSuccessValue(): void
{
$this->assertTrue(Success::create('foo')->error()->isEmpty());
$this->assertTrue(Success::create('foo')->success()->isDefined());
$this->assertSame('foo', Success::create('foo')->success()->get());
}
public function testSuccessMapping(): void
{
$r = Success::create('foo')
->map('strtoupper')
->mapError('ucfirst');
$this->assertTrue($r->success()->isDefined());
$this->assertSame('FOO', $r->success()->get());
}
public function testSuccessFlatMappingSuccess(): void
{
$r = Success::create('foo')->flatMap(function (string $data): Success {
return Success::create('OH YES');
});
$this->assertTrue($r->success()->isDefined());
$this->assertSame('OH YES', $r->success()->get());
}
public function testSuccessFlatMappingError(): void
{
$r = Success::create('foo')->flatMap(function (string $data): Error {
return Error::create('OH NO');
});
$this->assertTrue($r->error()->isDefined());
$this->assertSame('OH NO', $r->error()->get());
}
public function testSuccessFail(): void
{
$result = Success::create('foo');
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('None has no value.');
$result->error()->get();
}
public function testErrorValue(): void
{
$this->assertTrue(Error::create('foo')->error()->isDefined());
$this->assertTrue(Error::create('foo')->success()->isEmpty());
$this->assertSame('foo', Error::create('foo')->error()->get());
}
public function testErrorMapping(): void
{
$r = Error::create('foo')
->map('strtoupper')
->mapError('ucfirst');
$this->assertSame('Foo', $r->error()->get());
}
public function testErrorFail(): void
{
$result = Error::create('foo');
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('None has no value.');
$result->success()->get();
}
}

View File

@ -1,3 +1,18 @@
### 2.9.1 (2023-02-06)
* Fixed Logger not being serializable anymore (#1792)
### 2.9.0 (2023-02-05)
* Deprecated FlowdockHandler & Formatter as the flowdock service was shutdown (#1748)
* Added support for enum context values in PsrLogMessageProcessor (#1773)
* Added graylog2/gelf-php 2.x support (#1747)
* Improved `BrowserConsoleHandler` logging to use more appropriate methods than just console.log in the browser (#1739)
* Fixed `WhatFailureGroupHandler` not catching errors happening inside `close()` (#1791)
* Fixed datetime field in `GoogleCloudLoggingFormatter` (#1758)
* Fixed infinite loop detection within Fibers (#1753)
* Fixed `AmqpHandler->setExtraAttributes` not working with buffering handler wrappers (#1781)
### 2.8.0 (2022-07-24)
* Deprecated `CubeHandler` and `PHPConsoleHandler` as both projects are abandoned and those should not be used anymore (#1734)

View File

@ -21,7 +21,7 @@
"aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev",
"elasticsearch/elasticsearch": "^7 || ^8",
"graylog2/gelf-php": "^1.4.2",
"graylog2/gelf-php": "^1.4.2 || ^2@dev",
"guzzlehttp/guzzle": "^7.4",
"guzzlehttp/psr7": "^2.2",
"mongodb/mongodb": "^1.8",

View File

@ -15,6 +15,7 @@ namespace Monolog\Formatter;
* formats the record to be used in the FlowdockHandler
*
* @author Dominik Liebler <liebler.dominik@gmail.com>
* @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4
*/
class FlowdockFormatter implements FormatterInterface
{

View File

@ -47,6 +47,11 @@ class GelfMessageFormatter extends NormalizerFormatter
*/
protected $maxLength;
/**
* @var int
*/
private $gelfVersion = 2;
/**
* Translates Monolog log levels to Graylog2 log priorities.
*
@ -78,6 +83,10 @@ class GelfMessageFormatter extends NormalizerFormatter
$this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix;
$this->contextPrefix = $contextPrefix;
$this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength;
if (method_exists(Message::class, 'setFacility')) {
$this->gelfVersion = 1;
}
}
/**
@ -113,16 +122,20 @@ class GelfMessageFormatter extends NormalizerFormatter
$message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength));
}
if (isset($record['channel'])) {
$message->setFacility($record['channel']);
}
if (isset($extra['line'])) {
$message->setLine($extra['line']);
unset($extra['line']);
}
if (isset($extra['file'])) {
$message->setFile($extra['file']);
unset($extra['file']);
if ($this->gelfVersion === 1) {
if (isset($record['channel'])) {
$message->setFacility($record['channel']);
}
if (isset($extra['line'])) {
$message->setLine($extra['line']);
unset($extra['line']);
}
if (isset($extra['file'])) {
$message->setFile($extra['file']);
unset($extra['file']);
}
} else {
$message->setAdditional('facility', $record['channel']);
}
foreach ($extra as $key => $val) {
@ -147,11 +160,13 @@ class GelfMessageFormatter extends NormalizerFormatter
$message->setAdditional($this->contextPrefix . $key, $val);
}
/** @phpstan-ignore-next-line */
if (null === $message->getFile() && isset($context['exception']['file'])) {
if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) {
$message->setFile($matches[1]);
$message->setLine($matches[2]);
if ($this->gelfVersion === 1) {
/** @phpstan-ignore-next-line */
if (null === $message->getFile() && isset($context['exception']['file'])) {
if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) {
$message->setFile($matches[1]);
$message->setLine($matches[2]);
}
}
}

View File

@ -17,6 +17,7 @@ use Monolog\LogRecord;
/**
* Encodes message information into JSON in a format compatible with Cloud logging.
*
* @see https://cloud.google.com/logging/docs/structured-logging
* @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry
*
* @author Luís Cobucci <lcobucci@gmail.com>
@ -28,7 +29,7 @@ final class GoogleCloudLoggingFormatter extends JsonFormatter
{
// Re-key level for GCP logging
$record['severity'] = $record['level_name'];
$record['timestamp'] = $record['datetime']->format(DateTimeInterface::RFC3339_EXTENDED);
$record['time'] = $record['datetime']->format(DateTimeInterface::RFC3339_EXTENDED);
// Remove keys that are not used by GCP
unset($record['level'], $record['level_name'], $record['datetime']);

View File

@ -151,13 +151,14 @@ class AmqpHandler extends AbstractProcessingHandler
private function createAmqpMessage(string $data): AMQPMessage
{
return new AMQPMessage(
$data,
[
'delivery_mode' => 2,
'content_type' => 'application/json',
]
);
$attributes = [
'delivery_mode' => 2,
'content_type' => 'application/json',
];
if ($this->extraAttributes) {
$attributes = array_merge($attributes, $this->extraAttributes);
}
return new AMQPMessage($data, $attributes);
}
/**

View File

@ -14,6 +14,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Monolog\Utils;
use Monolog\Logger;
use function count;
use function headers_list;
@ -177,7 +178,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
$extra = static::dump('Extra', $record['extra']);
if (empty($context) && empty($extra)) {
$script[] = static::call_array('log', static::handleStyles($record['formatted']));
$script[] = static::call_array(static::getConsoleMethodForLevel($record['level']), static::handleStyles($record['formatted']));
} else {
$script = array_merge(
$script,
@ -192,6 +193,20 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);";
}
private static function getConsoleMethodForLevel(int $level): string
{
return [
Logger::DEBUG => 'debug',
Logger::INFO => 'info',
Logger::NOTICE => 'info',
Logger::WARNING => 'warn',
Logger::ERROR => 'error',
Logger::CRITICAL => 'error',
Logger::ALERT => 'error',
Logger::EMERGENCY => 'error',
][$level] ?? 'log';
}
/**
* @return string[]
*/

View File

@ -28,6 +28,7 @@ use Monolog\Formatter\FormatterInterface;
* @see https://www.flowdock.com/api/push
*
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
* @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4
*/
class FlowdockHandler extends SocketHandler
{

View File

@ -64,4 +64,18 @@ class WhatFailureGroupHandler extends GroupHandler
}
}
}
/**
* {@inheritDoc}
*/
public function close(): void
{
foreach ($this->handlers as $handler) {
try {
$handler->close();
} catch (\Throwable $e) {
// What failure?
}
}
}
}

View File

@ -168,6 +168,11 @@ class Logger implements LoggerInterface, ResettableInterface
*/
private $logDepth = 0;
/**
* @var \WeakMap<\Fiber, int>|null Keeps track of depth inside fibers to prevent infinite logging loops
*/
private $fiberLogDepth;
/**
* @var bool Whether to detect infinite logging loops
*
@ -189,6 +194,13 @@ class Logger implements LoggerInterface, ResettableInterface
$this->setHandlers($handlers);
$this->processors = $processors;
$this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC');
if (\PHP_VERSION_ID >= 80100) {
// Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412
/** @var \WeakMap<\Fiber, int> $fiberLogDepth */
$fiberLogDepth = new \WeakMap();
$this->fiberLogDepth = $fiberLogDepth;
}
}
public function getName(): string
@ -332,12 +344,20 @@ class Logger implements LoggerInterface, ResettableInterface
}
if ($this->detectCycles) {
$this->logDepth += 1;
if (\PHP_VERSION_ID >= 80100 && $fiber = \Fiber::getCurrent()) {
$this->fiberLogDepth[$fiber] = $this->fiberLogDepth[$fiber] ?? 0;
$logDepth = ++$this->fiberLogDepth[$fiber];
} else {
$logDepth = ++$this->logDepth;
}
} else {
$logDepth = 0;
}
if ($this->logDepth === 3) {
if ($logDepth === 3) {
$this->warning('A possible infinite logging loop was detected and aborted. It appears some of your handler code is triggering logging, see the previous log record for a hint as to what may be the cause.');
return false;
} elseif ($this->logDepth >= 5) { // log depth 4 is let through so we can log the warning above
} elseif ($logDepth >= 5) { // log depth 4 is let through, so we can log the warning above
return false;
}
@ -387,7 +407,11 @@ class Logger implements LoggerInterface, ResettableInterface
}
} finally {
if ($this->detectCycles) {
$this->logDepth--;
if (isset($fiber)) {
$this->fiberLogDepth[$fiber]--;
} else {
$this->logDepth--;
}
}
}
@ -698,4 +722,40 @@ class Logger implements LoggerInterface, ResettableInterface
($this->exceptionHandler)($e, $record);
}
/**
* @return array<string, mixed>
*/
public function __serialize(): array
{
return [
'name' => $this->name,
'handlers' => $this->handlers,
'processors' => $this->processors,
'microsecondTimestamps' => $this->microsecondTimestamps,
'timezone' => $this->timezone,
'exceptionHandler' => $this->exceptionHandler,
'logDepth' => $this->logDepth,
'detectCycles' => $this->detectCycles,
];
}
/**
* @param array<string, mixed> $data
*/
public function __unserialize(array $data): void
{
foreach (['name', 'handlers', 'processors', 'microsecondTimestamps', 'timezone', 'exceptionHandler', 'logDepth', 'detectCycles'] as $property) {
if (isset($data[$property])) {
$this->$property = $data[$property];
}
}
if (\PHP_VERSION_ID >= 80100) {
// Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412
/** @var \WeakMap<\Fiber, int> $fiberLogDepth */
$fiberLogDepth = new \WeakMap();
$this->fiberLogDepth = $fiberLogDepth;
}
}
}

View File

@ -66,6 +66,8 @@ class PsrLogMessageProcessor implements ProcessorInterface
} else {
$replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE);
}
} elseif ($val instanceof \UnitEnum) {
$replacements[$placeholder] = $val instanceof \BackedEnum ? $val->value : $val->name;
} elseif (is_object($val)) {
$replacements[$placeholder] = '[object '.Utils::getClass($val).']';
} elseif (is_array($val)) {

View File

@ -19,8 +19,8 @@
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8",
"phpunit/phpunit": "^8.5.28 || ^9.5.21"
"bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12"
},
"autoload": {
"psr-4": {

View File

@ -56,7 +56,11 @@ class Bencode
{
$start_decode = ($pos === 0); // If it is the root call ?
if ($start_decode && (!is_string($data) || strlen($data) == 0)) {
throw new ParseException('Decode Input is not valid String.');
throw new ParseException('Decode Input is not valid String');
}
if ($pos >= strlen($data)) {
throw new ParseException('Unterminated bencode string literal');
}
if ($data[$pos] === 'd') {
@ -69,7 +73,7 @@ class Bencode
break;
}
if (!is_string($key)) {
throw new ParseException('Non string key found in the dictionary.');
throw new ParseException('Non string key found in the dictionary');
} elseif (array_key_exists($key, $return)) {
throw new ParseException('Duplicate Dictionary key exist before: ' . $key);
}

View File

@ -53,7 +53,7 @@ class TorrentFile
protected static function checkTorrentDict($dict, $key, $type = null)
{
if (!is_array($dict)) {
throw new ParseException('Checking non-dictionary value.');
throw new ParseException('Checking non-dictionary value');
}
if (!isset($dict[$key])) {
@ -307,7 +307,7 @@ class TorrentFile
$allowedKeys = array_merge([
'name', 'private', 'piece length', // Common key
'files', 'pieces', 'length', // v1
'files tree', 'meta version', // v2
'file tree', 'meta version', // v2
], $allowedKeys);
foreach ($this->data['info'] as $key => $value) {
if (!in_array($key, $allowedKeys)) {
@ -578,7 +578,7 @@ class TorrentFile
if ($this->getProtocol() === self::PROTOCOL_V1) { // Do what we do in protocol v1
$pieces = self::checkTorrentDict($info, 'pieces', 'string');
if (strlen($pieces) % 20 != 0) {
throw new ParseException('Invalid pieces length.');
throw new ParseException('Invalid pieces length');
}
if ($this->getFileMode() === self::FILEMODE_SINGLE) {
@ -596,7 +596,7 @@ class TorrentFile
foreach ($paths as $path) {
if (!is_string($path)) {
throw new ParseException('Invalid path with non-string value.');
throw new ParseException('Invalid path with non-string value');
}
}
@ -635,7 +635,7 @@ class TorrentFile
$length = self::checkTorrentDict($file, 'length', 'integer');
if ($length > $pieceLength) { // check pieces root of large file is exist in $root['picec layers'] or not
if (!array_key_exists($piecesRoot, $pieceLayers)) {
throw new ParseException('Pieces not exist in piece layers.');
throw new ParseException('Pieces not exist in piece layers');
}
}
@ -643,7 +643,6 @@ class TorrentFile
$merkleTree = $length; // rewrite merkleTree to size, it's safe since it not affect $data['info']['file tree']
} else {
$parent_path = $paths; // store parent paths
/** @noinspection PhpParameterByRefIsNotUsedAsReferenceInspection */
foreach ($merkleTree as $k => &$v) { // Loop tree
$paths[] = $k; // push current path into paths
$loopMerkleTree($v, $paths); // Loop check

View File

@ -218,7 +218,7 @@ class DecodeTest extends TestCase
public function testDecodeDictionaryKeyNotString()
{
$this->expectException(ParseException::class);
$this->expectExceptionMessage('Non string key found in the dictionary.');
$this->expectExceptionMessage('Non string key found in the dictionary');
Bencode::decode('di123ei321ee');
}
@ -263,7 +263,7 @@ class DecodeTest extends TestCase
public function testDecodeNothing()
{
$this->expectException(ParseException::class);
$this->expectExceptionMessage('Decode Input is not valid String.');
$this->expectExceptionMessage('Decode Input is not valid String');
Bencode::decode('');
}
@ -274,7 +274,7 @@ class DecodeTest extends TestCase
public function testDecodeNull()
{
$this->expectException(ParseException::class);
$this->expectExceptionMessage('Decode Input is not valid String.');
$this->expectExceptionMessage('Decode Input is not valid String');
Bencode::decode(null);
}

View File

@ -60,7 +60,7 @@ class TorrentV1MultiTest extends TestCase
public function testFilesPathEntityNotString() {
$this->expectException(ParseException::class);
$this->expectExceptionMessage('Invalid path with non-string value.');
$this->expectExceptionMessage('Invalid path with non-string value');
$files = $this->torrent->getInfoField('files');
$files[0]['path'][0] = 123;

View File

@ -10,9 +10,9 @@ trait TorrentFileV1Trait
public function testV1WithWrongPieces() {
$this->expectException(ParseException::class);
$this->expectExceptionMessage('Invalid pieces length.');
$this->expectExceptionMessage('Invalid pieces length');
$this->torrent->setInfoField('pieces', $this->torrent->getRootField('pieces') . 'somestring');
$this->torrent->parse();
}
}
}

View File

@ -60,7 +60,7 @@ trait TorrentFileV2Trait
public function testNodePiecesRootNotExistInPieceLayer() {
$this->expectException(ParseException::class);
$this->expectExceptionMessage('Pieces not exist in piece layers.');
$this->expectExceptionMessage('Pieces not exist in piece layers');
$fileTree = $this->torrent->getInfoField('file tree');
$fileTree['file1.dat']['']['pieces root'] = hash('sha256', 'adfadsfasd',true);
@ -68,4 +68,4 @@ trait TorrentFileV2Trait
$this->torrent->setInfoField('file tree', $fileTree);
$this->torrent->parse();
}
}
}

4
vendor/symfony/console/.gitattributes vendored Normal file
View File

@ -0,0 +1,4 @@
/Tests export-ignore
/phpunit.xml.dist export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore

3
vendor/symfony/console/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml

View File

@ -276,7 +276,9 @@ class Application implements ResetInterface
$alternative = $alternatives[0];
$style = new SymfonyStyle($input, $output);
$style->block(sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error');
$output->writeln('');
$formattedBlock = (new FormatterHelper())->formatBlock(sprintf('Command "%s" is not defined.', $name), 'error', true);
$output->writeln($formattedBlock);
if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) {
if (null !== $this->dispatcher) {
$event = new ConsoleErrorEvent($input, $output, $e);
@ -933,11 +935,21 @@ class Application implements ResetInterface
}
switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) {
case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break;
case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break;
case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break;
case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break;
default: $shellVerbosity = 0; break;
case -1:
$output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
break;
case 1:
$output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
break;
case 2:
$output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
break;
case 3:
$output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
break;
default:
$shellVerbosity = 0;
break;
}
if (true === $input->hasParameterOption(['--quiet', '-q'], true)) {
@ -1000,10 +1012,6 @@ class Application implements ResetInterface
});
}
}
foreach ($commandSignals as $signal) {
$this->signalRegistry->register($signal, [$command, 'handleSignal']);
}
}
if (null !== $this->dispatcher) {
@ -1022,6 +1030,10 @@ class Application implements ResetInterface
});
}
}
foreach ($commandSignals as $signal) {
$this->signalRegistry->register($signal, [$command, 'handleSignal']);
}
}
if (null === $this->dispatcher) {

View File

@ -429,9 +429,9 @@ class Command
* @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
* @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
*
* @throws InvalidArgumentException When argument mode is not valid
*
* @return $this
*
* @throws InvalidArgumentException When argument mode is not valid
*/
public function addArgument(string $name, int $mode = null, string $description = '', $default = null)
{
@ -450,9 +450,9 @@ class Command
* @param int|null $mode The option mode: One of the InputOption::VALUE_* constants
* @param mixed $default The default value (must be null for InputOption::VALUE_NONE)
*
* @throws InvalidArgumentException If option mode is invalid or incompatible
*
* @return $this
*
* @throws InvalidArgumentException If option mode is invalid or incompatible
*/
public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
{

View File

@ -155,10 +155,10 @@ final class CompleteCommand extends Command
throw $e;
}
return self::FAILURE;
return 2;
}
return self::SUCCESS;
return 0;
}
private function createCompletionInput(InputInterface $input): CompletionInput

View File

@ -85,7 +85,7 @@ EOH
if ($input->getOption('debug')) {
$this->tailDebugLog($commandName, $output);
return self::SUCCESS;
return 0;
}
$shell = $input->getArgument('shell') ?? self::guessShell();
@ -93,15 +93,21 @@ EOH
if (!file_exists($completionFile)) {
$supportedShells = $this->getSupportedShells();
($output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output)
->writeln(sprintf('<error>Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").</>', $shell, implode('", "', $supportedShells)));
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
}
if ($shell) {
$output->writeln(sprintf('<error>Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").</>', $shell, implode('", "', $supportedShells)));
} else {
$output->writeln(sprintf('<error>Shell not detected, Symfony shell completion only supports "%s").</>', implode('", "', $supportedShells)));
}
return self::INVALID;
return 2;
}
$output->write(str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, $this->getApplication()->getVersion()], file_get_contents($completionFile)));
return self::SUCCESS;
return 0;
}
private static function guessShell(): string
@ -126,8 +132,14 @@ EOH
*/
private function getSupportedShells(): array
{
return array_map(function ($f) {
return pathinfo($f, \PATHINFO_EXTENSION);
}, glob(__DIR__.'/../Resources/completion.*'));
$shells = [];
foreach (new \DirectoryIterator(__DIR__.'/../Resources/') as $file) {
if (str_starts_with($file->getBasename(), 'completion.') && $file->isFile()) {
$shells[] = $file->getExtension();
}
}
return $shells;
}
}

View File

@ -12,7 +12,7 @@
namespace Symfony\Component\Console\Exception;
/**
* Represents an incorrect option name typed in the console.
* Represents an incorrect option name or value typed in the console.
*
* @author Jérôme Tamarelle <jerome@tamarelle.net>
*/

View File

@ -96,7 +96,8 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
{
if (null === $this->handlesHrefGracefully) {
$this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')
&& (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100);
&& (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100)
&& !isset($_SERVER['IDEA_INITIAL_DIRECTORY']);
}
if (null !== $this->href && $this->handlesHrefGracefully) {

View File

@ -171,6 +171,8 @@ abstract class Helper implements HelperInterface
$string = $formatter->format($string ?? '');
// remove already formatted characters
$string = preg_replace("/\033\[[^m]*m/", '', $string ?? '');
// remove terminal hyperlinks
$string = preg_replace('/\\033]8;[^;]*;[^\\033]*\\033\\\\/', '', $string ?? '');
$formatter->setDecorated($isDecorated);
return $string;

View File

@ -53,7 +53,6 @@ final class ProgressBar
private $startTime;
private $stepWidth;
private $percent = 0.0;
private $formatLineCount;
private $messages = [];
private $overwrite = true;
private $terminal;
@ -446,8 +445,6 @@ final class ProgressBar
} else {
$this->format = $format;
}
$this->formatLineCount = substr_count($this->format, "\n");
}
/**
@ -464,7 +461,7 @@ final class ProgressBar
if ($this->overwrite) {
if (null !== $this->previousMessage) {
if ($this->output instanceof ConsoleSectionOutput) {
$messageLines = explode("\n", $message);
$messageLines = explode("\n", $this->previousMessage);
$lineCount = \count($messageLines);
foreach ($messageLines as $messageLine) {
$messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine));
@ -474,7 +471,8 @@ final class ProgressBar
}
$this->output->clear($lineCount);
} else {
for ($i = 0; $i < $this->formatLineCount; ++$i) {
$lineCount = substr_count($this->previousMessage, "\n");
for ($i = 0; $i < $lineCount; ++$i) {
$this->cursor->moveToColumn(1);
$this->cursor->clearLine();
$this->cursor->moveUp();

View File

@ -128,7 +128,18 @@ class QuestionHelper extends Helper
}
if (false === $ret) {
$isBlocked = stream_get_meta_data($inputStream)['blocked'] ?? true;
if (!$isBlocked) {
stream_set_blocking($inputStream, true);
}
$ret = $this->readInput($inputStream, $question);
if (!$isBlocked) {
stream_set_blocking($inputStream, false);
}
if (false === $ret) {
throw new MissingInputException('Aborted.');
}
@ -500,13 +511,11 @@ class QuestionHelper extends Helper
return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r'));
}
if (!\function_exists('exec')) {
if (!\function_exists('shell_exec')) {
return self::$stdinIsInteractive = true;
}
exec('stty 2> /dev/null', $output, $status);
return self::$stdinIsInteractive = 1 !== $status;
return self::$stdinIsInteractive = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null'));
}
/**

View File

@ -805,7 +805,7 @@ class Table
$textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
$textLength = Helper::width($textContent);
if ($textLength > 0) {
$contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
$contentColumns = mb_str_split($textContent, ceil($textLength / $cell->getColspan()));
foreach ($contentColumns as $position => $content) {
$row[$i + $position] = $content;
}

View File

@ -32,7 +32,7 @@ class InputArgument
/**
* @param string $name The argument name
* @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL
* @param int|null $mode The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY
* @param string $description A description text
* @param string|bool|int|float|array|null $default The default value (for self::OPTIONAL mode only)
*

View File

@ -1,4 +1,4 @@
Copyright (c) 2004-2022 Fabien Potencier
Copyright (c) 2004-present Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -11,13 +11,14 @@ _sf_{{ COMMAND_NAME }}() {
local sf_cmd="${COMP_WORDS[0]}"
# for an alias, get the real script behind it
if [[ $(type -t $sf_cmd) == "alias" ]]; then
sf_cmd_type=$(type -t $sf_cmd)
if [[ $sf_cmd_type == "alias" ]]; then
sf_cmd=$(alias $sf_cmd | sed -E "s/alias $sf_cmd='(.*)'/\1/")
else
elif [[ $sf_cmd_type == "file" ]]; then
sf_cmd=$(type -p $sf_cmd)
fi
if [ ! -x "$sf_cmd" ]; then
if [[ $sf_cmd_type != "function" && ! -x $sf_cmd ]]; then
return 1
fi

View File

@ -64,20 +64,19 @@ class Terminal
return self::$stty;
}
// skip check if exec function is disabled
if (!\function_exists('exec')) {
// skip check if shell_exec function is disabled
if (!\function_exists('shell_exec')) {
return false;
}
exec('stty 2>&1', $output, $exitcode);
return self::$stty = 0 === $exitcode;
return self::$stty = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null'));
}
private static function initDimensions()
{
if ('\\' === \DIRECTORY_SEPARATOR) {
if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) {
$ansicon = getenv('ANSICON');
if (false !== $ansicon && preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim($ansicon), $matches)) {
// extract [w, H] from "wxh (WxH)"
// or [w, h] from "wxh"
self::$width = (int) $matches[1];
@ -157,6 +156,8 @@ class Terminal
2 => ['pipe', 'w'],
];
$cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0;
$process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]);
if (!\is_resource($process)) {
return null;
@ -167,6 +168,10 @@ class Terminal
fclose($pipes[2]);
proc_close($process);
if ($cp) {
sapi_windows_cp_set($cp);
}
return $info;
}
}

View File

@ -35,9 +35,9 @@ trait TesterTrait
/**
* Gets the display returned by the last execution of the command or application.
*
* @throws \RuntimeException If it's called before the execute method
*
* @return string
*
* @throws \RuntimeException If it's called before the execute method
*/
public function getDisplay(bool $normalize = false)
{
@ -103,9 +103,9 @@ trait TesterTrait
/**
* Gets the status code returned by the last execution of the command or application.
*
* @throws \RuntimeException If it's called before the execute method
*
* @return int
*
* @throws \RuntimeException If it's called before the execute method
*/
public function getStatusCode()
{

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Tests\CI;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\CI\GithubActionReporter;
use Symfony\Component\Console\Output\BufferedOutput;
class GithubActionReporterTest extends TestCase
{
public function testIsGithubActionEnvironment()
{
$prev = getenv('GITHUB_ACTIONS');
putenv('GITHUB_ACTIONS');
try {
self::assertFalse(GithubActionReporter::isGithubActionEnvironment());
putenv('GITHUB_ACTIONS=1');
self::assertTrue(GithubActionReporter::isGithubActionEnvironment());
} finally {
putenv('GITHUB_ACTIONS'.($prev ? "=$prev" : ''));
}
}
/**
* @dataProvider annotationsFormatProvider
*/
public function testAnnotationsFormat(string $type, string $message, string $file = null, int $line = null, int $col = null, string $expected)
{
$reporter = new GithubActionReporter($buffer = new BufferedOutput());
$reporter->{$type}($message, $file, $line, $col);
self::assertSame($expected.\PHP_EOL, $buffer->fetch());
}
public static function annotationsFormatProvider(): iterable
{
yield 'warning' => ['warning', 'A warning', null, null, null, '::warning::A warning'];
yield 'error' => ['error', 'An error', null, null, null, '::error::An error'];
yield 'debug' => ['debug', 'A debug log', null, null, null, '::debug::A debug log'];
yield 'with message to escape' => [
'debug',
"There are 100% chances\nfor this to be escaped properly\rRight?",
null,
null,
null,
'::debug::There are 100%25 chances%0Afor this to be escaped properly%0DRight?',
];
yield 'with meta' => [
'warning',
'A warning',
'foo/bar.php',
2,
4,
'::warning file=foo/bar.php,line=2,col=4::A warning',
];
yield 'with file property to escape' => [
'warning',
'A warning',
'foo,bar:baz%quz.php',
2,
4,
'::warning file=foo%2Cbar%3Abaz%25quz.php,line=2,col=4::A warning',
];
yield 'without file ignores col & line' => ['warning', 'A warning', null, 2, 4, '::warning::A warning'];
}
}

View File

@ -0,0 +1,62 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Color;
class ColorTest extends TestCase
{
public function testAnsiColors()
{
$color = new Color();
$this->assertSame(' ', $color->apply(' '));
$color = new Color('red', 'yellow');
$this->assertSame("\033[31;43m \033[39;49m", $color->apply(' '));
$color = new Color('bright-red', 'bright-yellow');
$this->assertSame("\033[91;103m \033[39;49m", $color->apply(' '));
$color = new Color('red', 'yellow', ['underscore']);
$this->assertSame("\033[31;43;4m \033[39;49;24m", $color->apply(' '));
}
public function testTrueColors()
{
if ('truecolor' !== getenv('COLORTERM')) {
$this->markTestSkipped('True color not supported.');
}
$color = new Color('#fff', '#000');
$this->assertSame("\033[38;2;255;255;255;48;2;0;0;0m \033[39;49m", $color->apply(' '));
$color = new Color('#ffffff', '#000000');
$this->assertSame("\033[38;2;255;255;255;48;2;0;0;0m \033[39;49m", $color->apply(' '));
}
public function testDegradedTrueColors()
{
$colorterm = getenv('COLORTERM');
putenv('COLORTERM=');
try {
$color = new Color('#f00', '#ff0');
$this->assertSame("\033[31;43m \033[39;49m", $color->apply(' '));
$color = new Color('#c0392b', '#f1c40f');
$this->assertSame("\033[31;43m \033[39;49m", $color->apply(' '));
} finally {
putenv('COLORTERM='.$colorterm);
}
}
}

View File

@ -0,0 +1,463 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Tests\Command;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidOptionException;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester;
class CommandTest extends TestCase
{
protected static $fixturesPath;
public static function setUpBeforeClass(): void
{
self::$fixturesPath = __DIR__.'/../Fixtures/';
require_once self::$fixturesPath.'/TestCommand.php';
}
public function testConstructor()
{
$command = new Command('foo:bar');
$this->assertEquals('foo:bar', $command->getName(), '__construct() takes the command name as its first argument');
}
public function testCommandNameCannotBeEmpty()
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('The command defined in "Symfony\Component\Console\Command\Command" cannot have an empty name.');
(new Application())->add(new Command());
}
public function testSetApplication()
{
$application = new Application();
$command = new \TestCommand();
$command->setApplication($application);
$this->assertEquals($application, $command->getApplication(), '->setApplication() sets the current application');
$this->assertEquals($application->getHelperSet(), $command->getHelperSet());
}
public function testSetApplicationNull()
{
$command = new \TestCommand();
$command->setApplication(null);
$this->assertNull($command->getHelperSet());
}
public function testSetGetDefinition()
{
$command = new \TestCommand();
$ret = $command->setDefinition($definition = new InputDefinition());
$this->assertEquals($command, $ret, '->setDefinition() implements a fluent interface');
$this->assertEquals($definition, $command->getDefinition(), '->setDefinition() sets the current InputDefinition instance');
$command->setDefinition([new InputArgument('foo'), new InputOption('bar')]);
$this->assertTrue($command->getDefinition()->hasArgument('foo'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument');
$this->assertTrue($command->getDefinition()->hasOption('bar'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument');
$command->setDefinition(new InputDefinition());
}
public function testAddArgument()
{
$command = new \TestCommand();
$ret = $command->addArgument('foo');
$this->assertEquals($command, $ret, '->addArgument() implements a fluent interface');
$this->assertTrue($command->getDefinition()->hasArgument('foo'), '->addArgument() adds an argument to the command');
}
public function testAddOption()
{
$command = new \TestCommand();
$ret = $command->addOption('foo');
$this->assertEquals($command, $ret, '->addOption() implements a fluent interface');
$this->assertTrue($command->getDefinition()->hasOption('foo'), '->addOption() adds an option to the command');
}
public function testSetHidden()
{
$command = new \TestCommand();
$command->setHidden(true);
$this->assertTrue($command->isHidden());
}
public function testGetNamespaceGetNameSetName()
{
$command = new \TestCommand();
$this->assertEquals('namespace:name', $command->getName(), '->getName() returns the command name');
$command->setName('foo');
$this->assertEquals('foo', $command->getName(), '->setName() sets the command name');
$ret = $command->setName('foobar:bar');
$this->assertEquals($command, $ret, '->setName() implements a fluent interface');
$this->assertEquals('foobar:bar', $command->getName(), '->setName() sets the command name');
}
/**
* @dataProvider provideInvalidCommandNames
*/
public function testInvalidCommandNames($name)
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage(sprintf('Command name "%s" is invalid.', $name));
$command = new \TestCommand();
$command->setName($name);
}
public static function provideInvalidCommandNames()
{
return [
[''],
['foo:'],
];
}
public function testGetSetDescription()
{
$command = new \TestCommand();
$this->assertEquals('description', $command->getDescription(), '->getDescription() returns the description');
$ret = $command->setDescription('description1');
$this->assertEquals($command, $ret, '->setDescription() implements a fluent interface');
$this->assertEquals('description1', $command->getDescription(), '->setDescription() sets the description');
}
public function testGetSetHelp()
{
$command = new \TestCommand();
$this->assertEquals('help', $command->getHelp(), '->getHelp() returns the help');
$ret = $command->setHelp('help1');
$this->assertEquals($command, $ret, '->setHelp() implements a fluent interface');
$this->assertEquals('help1', $command->getHelp(), '->setHelp() sets the help');
$command->setHelp('');
$this->assertEquals('', $command->getHelp(), '->getHelp() does not fall back to the description');
}
public function testGetProcessedHelp()
{
$command = new \TestCommand();
$command->setHelp('The %command.name% command does... Example: %command.full_name%.');
$this->assertStringContainsString('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly');
$this->assertStringNotContainsString('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name%');
$command = new \TestCommand();
$command->setHelp('');
$this->assertStringContainsString('description', $command->getProcessedHelp(), '->getProcessedHelp() falls back to the description');
$command = new \TestCommand();
$command->setHelp('The %command.name% command does... Example: %command.full_name%.');
$application = new Application();
$application->add($command);
$application->setDefaultCommand('namespace:name', true);
$this->assertStringContainsString('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly in single command applications');
$this->assertStringNotContainsString('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name% in single command applications');
}
public function testGetSetAliases()
{
$command = new \TestCommand();
$this->assertEquals(['name'], $command->getAliases(), '->getAliases() returns the aliases');
$ret = $command->setAliases(['name1']);
$this->assertEquals($command, $ret, '->setAliases() implements a fluent interface');
$this->assertEquals(['name1'], $command->getAliases(), '->setAliases() sets the aliases');
}
public function testGetSynopsis()
{
$command = new \TestCommand();
$command->addOption('foo');
$command->addArgument('bar');
$command->addArgument('info');
$this->assertEquals('namespace:name [--foo] [--] [<bar> [<info>]]', $command->getSynopsis(), '->getSynopsis() returns the synopsis');
}
public function testAddGetUsages()
{
$command = new \TestCommand();
$command->addUsage('foo1');
$command->addUsage('foo2');
$this->assertContains('namespace:name foo1', $command->getUsages());
$this->assertContains('namespace:name foo2', $command->getUsages());
}
public function testGetHelper()
{
$application = new Application();
$command = new \TestCommand();
$command->setApplication($application);
$formatterHelper = new FormatterHelper();
$this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->getHelper() returns the correct helper');
}
public function testGetHelperWithoutHelperSet()
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('Cannot retrieve helper "formatter" because there is no HelperSet defined.');
$command = new \TestCommand();
$command->getHelper('formatter');
}
public function testMergeApplicationDefinition()
{
$application1 = new Application();
$application1->getDefinition()->addArguments([new InputArgument('foo')]);
$application1->getDefinition()->addOptions([new InputOption('bar')]);
$command = new \TestCommand();
$command->setApplication($application1);
$command->setDefinition($definition = new InputDefinition([new InputArgument('bar'), new InputOption('foo')]));
$r = new \ReflectionObject($command);
$m = $r->getMethod('mergeApplicationDefinition');
$m->setAccessible(true);
$m->invoke($command);
$this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition() merges the application arguments and the command arguments');
$this->assertTrue($command->getDefinition()->hasArgument('bar'), '->mergeApplicationDefinition() merges the application arguments and the command arguments');
$this->assertTrue($command->getDefinition()->hasOption('foo'), '->mergeApplicationDefinition() merges the application options and the command options');
$this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition() merges the application options and the command options');
$m->invoke($command);
$this->assertEquals(3, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments and options');
}
public function testMergeApplicationDefinitionWithoutArgsThenWithArgsAddsArgs()
{
$application1 = new Application();
$application1->getDefinition()->addArguments([new InputArgument('foo')]);
$application1->getDefinition()->addOptions([new InputOption('bar')]);
$command = new \TestCommand();
$command->setApplication($application1);
$command->setDefinition($definition = new InputDefinition([]));
$r = new \ReflectionObject($command);
$m = $r->getMethod('mergeApplicationDefinition');
$m->setAccessible(true);
$m->invoke($command, false);
$this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition(false) merges the application and the command options');
$this->assertFalse($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(false) does not merge the application arguments');
$m->invoke($command, true);
$this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(true) merges the application arguments and the command arguments');
$m->invoke($command);
$this->assertEquals(2, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments');
}
public function testRunInteractive()
{
$tester = new CommandTester(new \TestCommand());
$tester->execute([], ['interactive' => true]);
$this->assertEquals('interact called'.\PHP_EOL.'execute called'.\PHP_EOL, $tester->getDisplay(), '->run() calls the interact() method if the input is interactive');
}
public function testRunNonInteractive()
{
$tester = new CommandTester(new \TestCommand());
$tester->execute([], ['interactive' => false]);
$this->assertEquals('execute called'.\PHP_EOL, $tester->getDisplay(), '->run() does not call the interact() method if the input is not interactive');
}
public function testExecuteMethodNeedsToBeOverridden()
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('You must override the execute() method in the concrete command class.');
$command = new Command('foo');
$command->run(new StringInput(''), new NullOutput());
}
public function testRunWithInvalidOption()
{
$this->expectException(InvalidOptionException::class);
$this->expectExceptionMessage('The "--bar" option does not exist.');
$command = new \TestCommand();
$tester = new CommandTester($command);
$tester->execute(['--bar' => true]);
}
public function testRunWithApplication()
{
$command = new \TestCommand();
$command->setApplication(new Application());
$exitCode = $command->run(new StringInput(''), new NullOutput());
$this->assertSame(0, $exitCode, '->run() returns an integer exit code');
}
public function testRunReturnsAlwaysInteger()
{
$command = new \TestCommand();
$this->assertSame(0, $command->run(new StringInput(''), new NullOutput()));
}
public function testRunWithProcessTitle()
{
$command = new \TestCommand();
$command->setApplication(new Application());
$command->setProcessTitle('foo');
$this->assertSame(0, $command->run(new StringInput(''), new NullOutput()));
if (\function_exists('cli_set_process_title')) {
if (null === @cli_get_process_title() && 'Darwin' === \PHP_OS) {
$this->markTestSkipped('Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.');
}
$this->assertEquals('foo', cli_get_process_title());
}
}
public function testSetCode()
{
$command = new \TestCommand();
$ret = $command->setCode(function (InputInterface $input, OutputInterface $output) {
$output->writeln('from the code...');
});
$this->assertEquals($command, $ret, '->setCode() implements a fluent interface');
$tester = new CommandTester($command);
$tester->execute([]);
$this->assertEquals('interact called'.\PHP_EOL.'from the code...'.\PHP_EOL, $tester->getDisplay());
}
public static function getSetCodeBindToClosureTests()
{
return [
[true, 'not bound to the command'],
[false, 'bound to the command'],
];
}
/**
* @dataProvider getSetCodeBindToClosureTests
*/
public function testSetCodeBindToClosure($previouslyBound, $expected)
{
$code = createClosure();
if ($previouslyBound) {
$code = $code->bindTo($this);
}
$command = new \TestCommand();
$command->setCode($code);
$tester = new CommandTester($command);
$tester->execute([]);
$this->assertEquals('interact called'.\PHP_EOL.$expected.\PHP_EOL, $tester->getDisplay());
}
public function testSetCodeWithStaticClosure()
{
$command = new \TestCommand();
$command->setCode(self::createClosure());
$tester = new CommandTester($command);
$tester->execute([]);
$this->assertEquals('interact called'.\PHP_EOL.'bound'.\PHP_EOL, $tester->getDisplay());
}
private static function createClosure()
{
return function (InputInterface $input, OutputInterface $output) {
$output->writeln(isset($this) ? 'bound' : 'not bound');
};
}
public function testSetCodeWithNonClosureCallable()
{
$command = new \TestCommand();
$ret = $command->setCode([$this, 'callableMethodCommand']);
$this->assertEquals($command, $ret, '->setCode() implements a fluent interface');
$tester = new CommandTester($command);
$tester->execute([]);
$this->assertEquals('interact called'.\PHP_EOL.'from the code...'.\PHP_EOL, $tester->getDisplay());
}
public function callableMethodCommand(InputInterface $input, OutputInterface $output)
{
$output->writeln('from the code...');
}
public function testSetCodeWithStaticAnonymousFunction()
{
$command = new \TestCommand();
$command->setCode(static function (InputInterface $input, OutputInterface $output) {
$output->writeln(isset($this) ? 'bound' : 'not bound');
});
$tester = new CommandTester($command);
$tester->execute([]);
$this->assertEquals('interact called'.\PHP_EOL.'not bound'.\PHP_EOL, $tester->getDisplay());
}
/**
* @requires PHP 8
*/
public function testCommandAttribute()
{
$this->assertSame('|foo|f', Php8Command::getDefaultName());
$this->assertSame('desc', Php8Command::getDefaultDescription());
$command = new Php8Command();
$this->assertSame('foo', $command->getName());
$this->assertSame('desc', $command->getDescription());
$this->assertTrue($command->isHidden());
$this->assertSame(['f'], $command->getAliases());
}
/**
* @requires PHP 8
*/
public function testDefaultCommand()
{
$apl = new Application();
$apl->setDefaultCommand(Php8Command::getDefaultName());
$property = new \ReflectionProperty($apl, 'defaultCommand');
$property->setAccessible(true);
$this->assertEquals('foo', $property->getValue($apl));
$apl->setDefaultCommand(Php8Command2::getDefaultName());
$property = new \ReflectionProperty($apl, 'defaultCommand');
$property->setAccessible(true);
$this->assertEquals('foo2', $property->getValue($apl));
}
}
// In order to get an unbound closure, we should create it outside a class
// scope.
function createClosure()
{
return function (InputInterface $input, OutputInterface $output) {
$output->writeln($this instanceof Command ? 'bound to the command' : 'not bound to the command');
};
}
#[AsCommand(name: 'foo', description: 'desc', hidden: true, aliases: ['f'])]
class Php8Command extends Command
{
}
#[AsCommand(name: 'foo2', description: 'desc2', hidden: true)]
class Php8Command2 extends Command
{
}

View File

@ -0,0 +1,151 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Tests\Command;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\CompleteCommand;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Output\BashCompletionOutput;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester;
class CompleteCommandTest extends TestCase
{
private $command;
private $application;
private $tester;
protected function setUp(): void
{
$this->command = new CompleteCommand();
$this->application = new Application();
$this->application->add(new CompleteCommandTest_HelloCommand());
$this->command->setApplication($this->application);
$this->tester = new CommandTester($this->command);
}
public function testRequiredShellOption()
{
$this->expectExceptionMessage('The "--shell" option must be set.');
$this->execute([]);
}
public function testUnsupportedShellOption()
{
$this->expectExceptionMessage('Shell completion is not supported for your shell: "unsupported" (supported: "bash").');
$this->execute(['--shell' => 'unsupported']);
}
public function testAdditionalShellSupport()
{
$this->command = new CompleteCommand(['supported' => BashCompletionOutput::class]);
$this->command->setApplication($this->application);
$this->tester = new CommandTester($this->command);
$this->execute(['--shell' => 'supported', '--current' => '1', '--input' => ['bin/console']]);
// verify that the default set of shells is still supported
$this->execute(['--shell' => 'bash', '--current' => '1', '--input' => ['bin/console']]);
$this->assertTrue(true);
}
/**
* @dataProvider provideInputAndCurrentOptionValues
*/
public function testInputAndCurrentOptionValidation(array $input, ?string $exceptionMessage)
{
if ($exceptionMessage) {
$this->expectExceptionMessage($exceptionMessage);
}
$this->execute($input + ['--shell' => 'bash']);
if (!$exceptionMessage) {
$this->tester->assertCommandIsSuccessful();
}
}
public static function provideInputAndCurrentOptionValues()
{
yield [[], 'The "--current" option must be set and it must be an integer'];
yield [['--current' => 'a'], 'The "--current" option must be set and it must be an integer'];
yield [['--current' => '1', '--input' => ['bin/console']], null];
yield [['--current' => '2', '--input' => ['bin/console']], 'Current index is invalid, it must be the number of input tokens or one more.'];
yield [['--current' => '1', '--input' => ['bin/console', 'cache:clear']], null];
yield [['--current' => '2', '--input' => ['bin/console', 'cache:clear']], null];
}
/**
* @dataProvider provideCompleteCommandNameInputs
*/
public function testCompleteCommandName(array $input, array $suggestions)
{
$this->execute(['--current' => '1', '--input' => $input]);
$this->assertEquals(implode("\n", $suggestions).\PHP_EOL, $this->tester->getDisplay());
}
public static function provideCompleteCommandNameInputs()
{
yield 'empty' => [['bin/console'], ['help', 'list', 'completion', 'hello', 'ahoy']];
yield 'partial' => [['bin/console', 'he'], ['help', 'list', 'completion', 'hello', 'ahoy']];
yield 'complete-shortcut-name' => [['bin/console', 'hell'], ['hello', 'ahoy']];
yield 'complete-aliases' => [['bin/console', 'ah'], ['hello', 'ahoy']];
}
/**
* @dataProvider provideCompleteCommandInputDefinitionInputs
*/
public function testCompleteCommandInputDefinition(array $input, array $suggestions)
{
$this->execute(['--current' => '2', '--input' => $input]);
$this->assertEquals(implode("\n", $suggestions).\PHP_EOL, $this->tester->getDisplay());
}
public static function provideCompleteCommandInputDefinitionInputs()
{
yield 'definition' => [['bin/console', 'hello', '-'], ['--help', '--quiet', '--verbose', '--version', '--ansi', '--no-ansi', '--no-interaction']];
yield 'custom' => [['bin/console', 'hello'], ['Fabien', 'Robin', 'Wouter']];
yield 'definition-aliased' => [['bin/console', 'ahoy', '-'], ['--help', '--quiet', '--verbose', '--version', '--ansi', '--no-ansi', '--no-interaction']];
yield 'custom-aliased' => [['bin/console', 'ahoy'], ['Fabien', 'Robin', 'Wouter']];
}
private function execute(array $input)
{
// run in verbose mode to assert exceptions
$this->tester->execute($input ? ($input + ['--shell' => 'bash']) : $input, ['verbosity' => OutputInterface::VERBOSITY_DEBUG]);
}
}
class CompleteCommandTest_HelloCommand extends Command
{
public function configure(): void
{
$this->setName('hello')
->setAliases(['ahoy'])
->addArgument('name', InputArgument::REQUIRED)
;
}
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestArgumentValuesFor('name')) {
$suggestions->suggestValues(['Fabien', 'Robin', 'Wouter']);
}
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Tests\Command;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Command\DumpCompletionCommand;
use Symfony\Component\Console\Tester\CommandCompletionTester;
class DumpCompletionCommandTest extends TestCase
{
/**
* @dataProvider provideCompletionSuggestions
*/
public function testComplete(array $input, array $expectedSuggestions)
{
$tester = new CommandCompletionTester(new DumpCompletionCommand());
$suggestions = $tester->complete($input);
$this->assertSame($expectedSuggestions, $suggestions);
}
public static function provideCompletionSuggestions()
{
yield 'shell' => [
[''],
['bash'],
];
}
}

View File

@ -0,0 +1,103 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Tests\Command;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\ListCommand;
use Symfony\Component\Console\Tester\CommandCompletionTester;
use Symfony\Component\Console\Tester\CommandTester;
class HelpCommandTest extends TestCase
{
public function testExecuteForCommandAlias()
{
$command = new HelpCommand();
$command->setApplication(new Application());
$commandTester = new CommandTester($command);
$commandTester->execute(['command_name' => 'li'], ['decorated' => false]);
$this->assertStringContainsString('list [options] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias');
$this->assertStringContainsString('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias');
$this->assertStringContainsString('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias');
}
public function testExecuteForCommand()
{
$command = new HelpCommand();
$commandTester = new CommandTester($command);
$command->setCommand(new ListCommand());
$commandTester->execute([], ['decorated' => false]);
$this->assertStringContainsString('list [options] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
$this->assertStringContainsString('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
$this->assertStringContainsString('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
}
public function testExecuteForCommandWithXmlOption()
{
$command = new HelpCommand();
$commandTester = new CommandTester($command);
$command->setCommand(new ListCommand());
$commandTester->execute(['--format' => 'xml']);
$this->assertStringContainsString('<command', $commandTester->getDisplay(), '->execute() returns an XML help text if --xml is passed');
}
public function testExecuteForApplicationCommand()
{
$application = new Application();
$commandTester = new CommandTester($application->get('help'));
$commandTester->execute(['command_name' => 'list']);
$this->assertStringContainsString('list [options] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
$this->assertStringContainsString('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
$this->assertStringContainsString('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
}
public function testExecuteForApplicationCommandWithXmlOption()
{
$application = new Application();
$commandTester = new CommandTester($application->get('help'));
$commandTester->execute(['command_name' => 'list', '--format' => 'xml']);
$this->assertStringContainsString('list [--raw] [--format FORMAT] [--short] [--] [&lt;namespace&gt;]', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
$this->assertStringContainsString('<command', $commandTester->getDisplay(), '->execute() returns an XML help text if --format=xml is passed');
}
/**
* @dataProvider provideCompletionSuggestions
*/
public function testComplete(array $input, array $expectedSuggestions)
{
require_once realpath(__DIR__.'/../Fixtures/FooCommand.php');
$application = new Application();
$application->add(new \FooCommand());
$tester = new CommandCompletionTester($application->get('help'));
$suggestions = $tester->complete($input, 2);
$this->assertSame($expectedSuggestions, $suggestions);
}
public static function provideCompletionSuggestions()
{
yield 'option --format' => [
['--format', ''],
['txt', 'xml', 'json', 'md'],
];
yield 'nothing' => [
[''],
['completion', 'help', 'list', 'foo:bar'],
];
yield 'command_name' => [
['f'],
['completion', 'help', 'list', 'foo:bar'],
];
}
}

View File

@ -0,0 +1,147 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Tests\Command;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandCompletionTester;
use Symfony\Component\Console\Tester\CommandTester;
class ListCommandTest extends TestCase
{
public function testExecuteListsCommands()
{
$application = new Application();
$commandTester = new CommandTester($command = $application->get('list'));
$commandTester->execute(['command' => $command->getName()], ['decorated' => false]);
$this->assertMatchesRegularExpression('/help\s{2,}Display help for a command/', $commandTester->getDisplay(), '->execute() returns a list of available commands');
}
public function testExecuteListsCommandsWithXmlOption()
{
$application = new Application();
$commandTester = new CommandTester($command = $application->get('list'));
$commandTester->execute(['command' => $command->getName(), '--format' => 'xml']);
$this->assertMatchesRegularExpression('/<command id="list" name="list" hidden="0">/', $commandTester->getDisplay(), '->execute() returns a list of available commands in XML if --xml is passed');
}
public function testExecuteListsCommandsWithRawOption()
{
$application = new Application();
$commandTester = new CommandTester($command = $application->get('list'));
$commandTester->execute(['command' => $command->getName(), '--raw' => true]);
$output = <<<'EOF'
completion Dump the shell completion script
help Display help for a command
list List commands
EOF;
$this->assertEquals($output, $commandTester->getDisplay(true));
}
public function testExecuteListsCommandsWithNamespaceArgument()
{
require_once realpath(__DIR__.'/../Fixtures/FooCommand.php');
$application = new Application();
$application->add(new \FooCommand());
$commandTester = new CommandTester($command = $application->get('list'));
$commandTester->execute(['command' => $command->getName(), 'namespace' => 'foo', '--raw' => true]);
$output = <<<'EOF'
foo:bar The foo:bar command
EOF;
$this->assertEquals($output, $commandTester->getDisplay(true));
}
public function testExecuteListsCommandsOrder()
{
require_once realpath(__DIR__.'/../Fixtures/Foo6Command.php');
$application = new Application();
$application->add(new \Foo6Command());
$commandTester = new CommandTester($command = $application->get('list'));
$commandTester->execute(['command' => $command->getName()], ['decorated' => false]);
$output = <<<'EOF'
Console Tool
Usage:
command [options] [arguments]
Options:
-h, --help Display help for the given command. When no command is given display help for the list command
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Available commands:
completion Dump the shell completion script
help Display help for a command
list List commands
0foo
0foo:bar 0foo:bar command
EOF;
$this->assertEquals($output, trim($commandTester->getDisplay(true)));
}
public function testExecuteListsCommandsOrderRaw()
{
require_once realpath(__DIR__.'/../Fixtures/Foo6Command.php');
$application = new Application();
$application->add(new \Foo6Command());
$commandTester = new CommandTester($command = $application->get('list'));
$commandTester->execute(['command' => $command->getName(), '--raw' => true]);
$output = <<<'EOF'
completion Dump the shell completion script
help Display help for a command
list List commands
0foo:bar 0foo:bar command
EOF;
$this->assertEquals($output, trim($commandTester->getDisplay(true)));
}
/**
* @dataProvider provideCompletionSuggestions
*/
public function testComplete(array $input, array $expectedSuggestions)
{
require_once realpath(__DIR__.'/../Fixtures/FooCommand.php');
$application = new Application();
$application->add(new \FooCommand());
$tester = new CommandCompletionTester($application->get('list'));
$suggestions = $tester->complete($input, 2);
$this->assertSame($expectedSuggestions, $suggestions);
}
public static function provideCompletionSuggestions()
{
yield 'option --format' => [
['--format', ''],
['txt', 'xml', 'json', 'md'],
];
yield 'namespace' => [
[''],
['_global', 'foo'],
];
yield 'namespace started' => [
['f'],
['_global', 'foo'],
];
}
}

Some files were not shown because too many files have changed in this diff Show More