Commit f2f8ce7a by 冷斌

fix bug

parent a96b259d
......@@ -2,6 +2,5 @@
"require": {
"php": ">=5.4.0",
"yansongda/pay": "2.7.8"
},
"minimum-stability": "dev"
}
}
......@@ -6,6 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
);
......@@ -9,7 +9,6 @@ return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
......
......@@ -8,7 +8,6 @@ $baseDir = dirname($vendorDir);
return array(
'Yansongda\\Supports\\' => array($vendorDir . '/yansongda/supports/src'),
'Yansongda\\Pay\\' => array($vendorDir . '/yansongda/pay/src'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
......
......@@ -10,7 +10,6 @@ class ComposerStaticInit6ca204ee4b311fba144444fd09f9bb55
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
......@@ -25,7 +24,6 @@ class ComposerStaticInit6ca204ee4b311fba144444fd09f9bb55
),
'S' =>
array (
'Symfony\\Polyfill\\Php80\\' => 23,
'Symfony\\Polyfill\\Php72\\' => 23,
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
......@@ -60,10 +58,6 @@ class ComposerStaticInit6ca204ee4b311fba144444fd09f9bb55
array (
0 => __DIR__ . '/..' . '/yansongda/pay/src',
),
'Symfony\\Polyfill\\Php80\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
),
'Symfony\\Polyfill\\Php72\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
......@@ -118,17 +112,11 @@ class ComposerStaticInit6ca204ee4b311fba144444fd09f9bb55
),
);
public static $classMap = array (
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit6ca204ee4b311fba144444fd09f9bb55::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit6ca204ee4b311fba144444fd09f9bb55::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit6ca204ee4b311fba144444fd09f9bb55::$classMap;
}, null, ClassLoader::class);
}
......
[
{
"name": "guzzlehttp/guzzle",
"version": "6.5.x-dev",
"version_normalized": "6.5.9999999.9999999-dev",
"version": "6.5.2",
"version_normalized": "6.5.2.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "400cefd25a23a3098486bfb52685b5367a464171"
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/400cefd25a23a3098486bfb52685b5367a464171",
"reference": "400cefd25a23a3098486bfb52685b5367a464171",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82",
"shasum": "",
"mirrors": [
{
......@@ -35,7 +35,7 @@
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"time": "2019-12-30T04:52:42+00:00",
"time": "2019-12-23T11:57:10+00:00",
"type": "library",
"extra": {
"branch-alias": {
......@@ -76,17 +76,17 @@
},
{
"name": "guzzlehttp/promises",
"version": "dev-master",
"version_normalized": "9999999-dev",
"version": "v1.3.1",
"version_normalized": "1.3.1.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "89b1a76b7fda5853401297dc4b2a093cba1fda23"
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/89b1a76b7fda5853401297dc4b2a093cba1fda23",
"reference": "89b1a76b7fda5853401297dc4b2a093cba1fda23",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": "",
"mirrors": [
{
......@@ -96,12 +96,12 @@
]
},
"require": {
"php": ">=5.6"
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^7.5"
"phpunit/phpunit": "^4.0"
},
"time": "2020-02-15T23:33:03+00:00",
"time": "2016-12-20T10:07:11+00:00",
"type": "library",
"extra": {
"branch-alias": {
......@@ -135,17 +135,17 @@
},
{
"name": "guzzlehttp/psr7",
"version": "1.x-dev",
"version_normalized": "1.9999999.9999999.9999999-dev",
"version": "1.6.1",
"version_normalized": "1.6.1.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "c73b502efd02beb2602500aa36793fb405e383ac"
"reference": "239400de7a173fe9901b9ac7c06497751f00727a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/c73b502efd02beb2602500aa36793fb405e383ac",
"reference": "c73b502efd02beb2602500aa36793fb405e383ac",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a",
"shasum": "",
"mirrors": [
{
......@@ -167,9 +167,9 @@
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
},
"time": "2020-02-12T23:13:46+00:00",
"time": "2019-07-01T23:21:34+00:00",
"type": "library",
"extra": {
"branch-alias": {
......@@ -214,17 +214,17 @@
},
{
"name": "monolog/monolog",
"version": "1.x-dev",
"version_normalized": "1.9999999.9999999.9999999-dev",
"version": "1.25.3",
"version_normalized": "1.25.3.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "5c670ec3d2cebcc3c20f014f5b8fe2087e434a60"
"reference": "fa82921994db851a8becaf3787a9e73c5976b6f1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/5c670ec3d2cebcc3c20f014f5b8fe2087e434a60",
"reference": "5c670ec3d2cebcc3c20f014f5b8fe2087e434a60",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/fa82921994db851a8becaf3787a9e73c5976b6f1",
"reference": "fa82921994db851a8becaf3787a9e73c5976b6f1",
"shasum": "",
"mirrors": [
{
......@@ -266,7 +266,7 @@
"ruflin/elastica": "Allow sending log messages to an Elastic Search server",
"sentry/sentry": "Allow sending log messages to a Sentry server"
},
"time": "2020-03-13T16:46:09+00:00",
"time": "2019-12-20T14:15:16+00:00",
"type": "library",
"extra": {
"branch-alias": {
......@@ -300,17 +300,17 @@
},
{
"name": "psr/http-message",
"version": "dev-master",
"version_normalized": "9999999-dev",
"version": "1.0.1",
"version_normalized": "1.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4"
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/efd67d1dc14a7ef4fc4e518e7dee91c271d524e4",
"reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": "",
"mirrors": [
{
......@@ -322,7 +322,7 @@
"require": {
"php": ">=5.3.0"
},
"time": "2019-08-29T13:16:46+00:00",
"time": "2016-08-06T14:39:51+00:00",
"type": "library",
"extra": {
"branch-alias": {
......@@ -358,8 +358,8 @@
},
{
"name": "psr/log",
"version": "dev-master",
"version_normalized": "9999999-dev",
"version": "1.1.3",
"version_normalized": "1.1.3.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
......@@ -461,17 +461,17 @@
},
{
"name": "symfony/event-dispatcher",
"version": "4.4.x-dev",
"version_normalized": "4.4.9999999.9999999-dev",
"version": "v4.4.5",
"version_normalized": "4.4.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "cf57788d1ca64ee7e689698dc0295d25c9fe3780"
"reference": "4ad8e149799d3128621a3a1f70e92b9897a8930d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/cf57788d1ca64ee7e689698dc0295d25c9fe3780",
"reference": "cf57788d1ca64ee7e689698dc0295d25c9fe3780",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4ad8e149799d3128621a3a1f70e92b9897a8930d",
"reference": "4ad8e149799d3128621a3a1f70e92b9897a8930d",
"shasum": "",
"mirrors": [
{
......@@ -504,7 +504,7 @@
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"time": "2020-03-16T11:24:17+00:00",
"time": "2020-02-04T09:32:40+00:00",
"type": "library",
"extra": {
"branch-alias": {
......@@ -605,17 +605,17 @@
},
{
"name": "symfony/http-foundation",
"version": "4.4.x-dev",
"version_normalized": "4.4.9999999.9999999-dev",
"version": "v4.4.5",
"version_normalized": "4.4.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "0a3b7711229f816a06fac805f4ed4a8f4641c719"
"reference": "7e41b4fcad4619535f45f8bfa7744c4f384e1648"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/0a3b7711229f816a06fac805f4ed4a8f4641c719",
"reference": "0a3b7711229f816a06fac805f4ed4a8f4641c719",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/7e41b4fcad4619535f45f8bfa7744c4f384e1648",
"reference": "7e41b4fcad4619535f45f8bfa7744c4f384e1648",
"shasum": "",
"mirrors": [
{
......@@ -633,7 +633,7 @@
"predis/predis": "~1.0",
"symfony/expression-language": "^3.4|^4.0|^5.0"
},
"time": "2020-03-23T12:37:11+00:00",
"time": "2020-02-13T19:40:01+00:00",
"type": "library",
"extra": {
"branch-alias": {
......@@ -668,17 +668,17 @@
},
{
"name": "symfony/mime",
"version": "dev-master",
"version_normalized": "9999999-dev",
"version": "v5.0.5",
"version_normalized": "5.0.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
"reference": "611f285c5ff1002be05089d34267aecf1a51da3d"
"reference": "9b3e5b5e58c56bbd76628c952d2b78556d305f3c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/611f285c5ff1002be05089d34267aecf1a51da3d",
"reference": "611f285c5ff1002be05089d34267aecf1a51da3d",
"url": "https://api.github.com/repos/symfony/mime/zipball/9b3e5b5e58c56bbd76628c952d2b78556d305f3c",
"reference": "9b3e5b5e58c56bbd76628c952d2b78556d305f3c",
"shasum": "",
"mirrors": [
{
......@@ -690,8 +690,7 @@
"require": {
"php": "^7.2.5",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.15"
"symfony/polyfill-mbstring": "^1.0"
},
"conflict": {
"symfony/mailer": "<4.4"
......@@ -700,11 +699,11 @@
"egulias/email-validator": "^2.1.10",
"symfony/dependency-injection": "^4.4|^5.0"
},
"time": "2020-03-16T16:46:21+00:00",
"time": "2020-02-04T09:41:09+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
"dev-master": "5.0-dev"
}
},
"installation-source": "source",
......@@ -739,17 +738,17 @@
},
{
"name": "symfony/polyfill-intl-idn",
"version": "dev-master",
"version_normalized": "9999999-dev",
"version": "v1.14.0",
"version_normalized": "1.14.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf"
"reference": "6842f1a39cf7d580655688069a03dd7cd83d244a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
"reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6842f1a39cf7d580655688069a03dd7cd83d244a",
"reference": "6842f1a39cf7d580655688069a03dd7cd83d244a",
"shasum": "",
"mirrors": [
{
......@@ -766,11 +765,11 @@
"suggest": {
"ext-intl": "For best performance"
},
"time": "2020-03-09T19:04:49+00:00",
"time": "2020-01-17T12:01:36+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-master": "1.14-dev"
}
},
"installation-source": "source",
......@@ -809,17 +808,17 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "dev-master",
"version_normalized": "9999999-dev",
"version": "v1.14.0",
"version_normalized": "1.14.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
"reference": "34094cfa9abe1f0f14f48f490772db7a775559f2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/34094cfa9abe1f0f14f48f490772db7a775559f2",
"reference": "34094cfa9abe1f0f14f48f490772db7a775559f2",
"shasum": "",
"mirrors": [
{
......@@ -834,11 +833,11 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2020-03-09T19:04:49+00:00",
"time": "2020-01-13T11:15:53+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-master": "1.14-dev"
}
},
"installation-source": "source",
......@@ -876,17 +875,17 @@
},
{
"name": "symfony/polyfill-php72",
"version": "dev-master",
"version_normalized": "9999999-dev",
"version": "v1.14.0",
"version_normalized": "1.14.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "37b0976c78b94856543260ce09b460a7bc852747"
"reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747",
"reference": "37b0976c78b94856543260ce09b460a7bc852747",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf",
"reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf",
"shasum": "",
"mirrors": [
{
......@@ -898,11 +897,11 @@
"require": {
"php": ">=5.3.3"
},
"time": "2020-02-27T09:26:54+00:00",
"time": "2020-01-13T11:15:53+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-master": "1.14-dev"
}
},
"installation-source": "source",
......@@ -938,76 +937,6 @@
]
},
{
"name": "symfony/polyfill-php80",
"version": "dev-master",
"version_normalized": "9999999-dev",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "8854dc880784d2ae32908b75824754339b5c0555"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/8854dc880784d2ae32908b75824754339b5c0555",
"reference": "8854dc880784d2ae32908b75824754339b5c0555",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.0.8"
},
"time": "2020-03-03T16:59:03+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"files": [
"bootstrap.php"
],
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
]
},
{
"name": "yansongda/pay",
"version": "v2.7.8",
"version_normalized": "2.7.8.0",
......
language: php
sudo: false
php:
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
- 7.4
- nightly
before_script:
- curl --version
- composer install --no-interaction --prefer-source --dev
- ~/.nvm/nvm.sh install v0.6.14
- ~/.nvm/nvm.sh run v0.6.14
- if [[ "$TRAVIS_PHP_VERSION" != "7.0" || "$TRAVIS_PHP_VERSION" != "7.1" ]]; then echo "xdebug.overload_var_dump = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini || true; fi
script: make test
matrix:
allow_failures:
- php: hhvm
dist: trusty
- php: nightly
include:
- php: 5.5
dist: trusty
- php: 5.6
dist: xenial
- php: 7.0
dist: xenial
- php: 7.1
dist: bionic
- php: 7.2
dist: bionic
- php: 7.3
dist: bionic
- php: 7.4
dist: bionic
- php: nightly
dist: bionic
env: COMPOSER_ARGS="--ignore-platform-reqs"
- php: hhvm-3.24
- php: hhvm
dist: trusty
allow_failures:
- php: hhvm-3.24
- php: nightly
fast_finish: true
install:
- if [[ "$TRAVIS_PHP_VERSION" != "hhvm-3.24" || "$TRAVIS_PHP_VERSION" != "nightly" ]]; then echo "xdebug.overload_var_dump = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini || true; fi
- composer install --prefer-dist $COMPOSER_ARGS
- ~/.nvm/nvm.sh install v10.18.0
- ~/.nvm/nvm.sh run v10.18.0
before_script:
- curl --version
script:
- make test
before_deploy:
- make package
......
......@@ -178,7 +178,7 @@ var GuzzleServer = function(port, log) {
that.responses = JSON.parse(request.body);
for (var i = 0; i < that.responses.length; i++) {
if (that.responses[i].body) {
that.responses[i].body = new Buffer.from(that.responses[i].body, 'base64');
that.responses[i].body = new Buffer(that.responses[i].body, 'base64');
}
}
if (that.log) {
......
artifacts/
vendor/
composer.lock
phpunit.xml
composer.phar
composer.lock
composer-test.lock
vendor/
build/artifacts/
artifacts/
docs/_build
docs/*.pyc
.idea
.DS_STORE
language: php
dist: xenial
sudo: false
cache:
directories:
- $HOME/.composer/cache/files
php:
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
- 7.4
- hhvm
env:
global:
- TEST_COMMAND="composer test"
matrix:
allow_failures:
- php: hhvm
fast_finish: true
include:
- php: 5.6
- php: 5.5
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci"
before_install:
- if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi
install:
# To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355
- if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi
- travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction
script:
......
......@@ -88,7 +88,7 @@ $promise
});
// Resolving the promise triggers the $onFulfilled callbacks and outputs
// "Hello, reader."
// "Hello, reader".
$promise->resolve('reader.');
```
......
......@@ -11,10 +11,10 @@
}
],
"require": {
"php": ">=5.6"
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^7.5"
"phpunit/phpunit": "^4.0"
},
"autoload": {
"psr-4": {
......@@ -22,11 +22,6 @@
},
"files": ["src/functions_include.php"]
},
"autoload-dev": {
"psr-4": {
"GuzzleHttp\\Promise\\Tests\\": "tests/"
}
},
"scripts": {
"test": "vendor/bin/phpunit",
"test-ci": "vendor/bin/phpunit --coverage-text"
......
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
colors="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTestsThatDoNotTestAnything="true"
bootstrap="vendor/autoload.php"
>
<phpunit colors="true" bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="GuzzleHttp Promise Test Suite">
<directory>tests/</directory>
......@@ -12,7 +7,7 @@
</testsuites>
<filter>
<whitelist>
<directory>src/</directory>
<directory suffix=".php">src/</directory>
<exclude>
<directory suffix="Interface.php">src/</directory>
</exclude>
......
......@@ -65,13 +65,7 @@ final class Coroutine implements PromiseInterface
$this->currentPromise->wait();
}
});
try {
$this->nextCoroutine($this->generator->current());
} catch (\Exception $exception) {
$this->result->reject($exception);
} catch (Throwable $throwable) {
$this->result->reject($throwable);
}
$this->nextCoroutine($this->generator->current());
}
public function then(
......
......@@ -74,9 +74,7 @@ class EachPromise implements PromisorInterface
try {
$this->createPromise();
$this->iterable->rewind();
if (!$this->checkIfFinished()) {
$this->refillPending();
}
$this->refillPending();
} catch (\Throwable $e) {
$this->aggregate->reject($e);
} catch (\Exception $e) {
......@@ -91,6 +89,11 @@ class EachPromise implements PromisorInterface
$this->mutex = false;
$this->aggregate = new Promise(function () {
reset($this->pending);
if (empty($this->pending) && !$this->iterable->valid()) {
$this->aggregate->resolve(null);
return;
}
// Consume a potentially fluctuating list of promises while
// ensuring that indexes are maintained (precluding array_shift).
while ($promise = current($this->pending)) {
......@@ -146,27 +149,21 @@ class EachPromise implements PromisorInterface
}
$promise = promise_for($this->iterable->current());
$key = $this->iterable->key();
// Iterable keys may not be unique, so we add the promises at the end
// of the pending array and retrieve the array index being used
$this->pending[] = null;
end($this->pending);
$idx = key($this->pending);
$idx = $this->iterable->key();
$this->pending[$idx] = $promise->then(
function ($value) use ($idx, $key) {
function ($value) use ($idx) {
if ($this->onFulfilled) {
call_user_func(
$this->onFulfilled, $value, $key, $this->aggregate
$this->onFulfilled, $value, $idx, $this->aggregate
);
}
$this->step($idx);
},
function ($reason) use ($idx, $key) {
function ($reason) use ($idx) {
if ($this->onRejected) {
call_user_func(
$this->onRejected, $reason, $key, $this->aggregate
$this->onRejected, $reason, $idx, $this->aggregate
);
}
$this->step($idx);
......
......@@ -13,7 +13,7 @@ class FulfilledPromise implements PromiseInterface
public function __construct($value)
{
if (is_object($value) && method_exists($value, 'then')) {
if (method_exists($value, 'then')) {
throw new \InvalidArgumentException(
'You cannot create a FulfilledPromise with a promise.');
}
......
......@@ -41,8 +41,9 @@ class Promise implements PromiseInterface
// Return a fulfilled promise and immediately invoke any callbacks.
if ($this->state === self::FULFILLED) {
$promise = promise_for($this->result);
return $onFulfilled ? $promise->then($onFulfilled) : $promise;
return $onFulfilled
? promise_for($this->result)->then($onFulfilled)
: promise_for($this->result);
}
// It's either cancelled or rejected, so return a rejected promise
......@@ -60,15 +61,19 @@ class Promise implements PromiseInterface
{
$this->waitIfPending();
if ($this->result instanceof PromiseInterface) {
return $this->result->wait($unwrap);
}
$inner = $this->result instanceof PromiseInterface
? $this->result->wait($unwrap)
: $this->result;
if ($unwrap) {
if ($this->state === self::FULFILLED) {
return $this->result;
if ($this->result instanceof PromiseInterface
|| $this->state === self::FULFILLED
) {
return $inner;
} else {
// It's rejected so "unwrap" and throw an exception.
throw exception_for($inner);
}
// It's rejected so "unwrap" and throw an exception.
throw exception_for($this->result);
}
}
......@@ -143,7 +148,7 @@ class Promise implements PromiseInterface
// If the value was not a settled promise or a thenable, then resolve
// it in the task queue using the correct ID.
if (!is_object($value) || !method_exists($value, 'then')) {
if (!method_exists($value, 'then')) {
$id = $state === self::FULFILLED ? 1 : 2;
// It's a success, so resolve the handlers in the queue.
queue()->add(static function () use ($id, $value, $handlers) {
......@@ -219,7 +224,7 @@ class Promise implements PromiseInterface
} elseif ($this->waitList) {
$this->invokeWaitList();
} else {
// If there's no wait function, then reject the promise.
// If there's not wait function, then reject the promise.
$this->reject('Cannot wait on a promise that has '
. 'no internal wait function. You must provide a wait '
. 'function when constructing the promise to be able to '
......@@ -258,13 +263,17 @@ class Promise implements PromiseInterface
$this->waitList = null;
foreach ($waitList as $result) {
do {
while (true) {
$result->waitIfPending();
$result = $result->result;
} while ($result instanceof Promise);
if ($result instanceof PromiseInterface) {
$result->wait(false);
if ($result->result instanceof Promise) {
$result = $result->result;
} else {
if ($result->result instanceof PromiseInterface) {
$result->result->wait(false);
}
break;
}
}
}
}
......
......@@ -13,7 +13,7 @@ class RejectedPromise implements PromiseInterface
public function __construct($reason)
{
if (is_object($reason) && method_exists($reason, 'then')) {
if (method_exists($reason, 'then')) {
throw new \InvalidArgumentException(
'You cannot create a RejectedPromise with a promise.');
}
......
......@@ -70,7 +70,7 @@ function promise_for($value)
}
// Return a Guzzle promise that shadows the given promise.
if (is_object($value) && method_exists($value, 'then')) {
if (method_exists($value, 'then')) {
$wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null;
$cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
$promise = new Promise($wfn, $cfn);
......@@ -213,14 +213,13 @@ function unwrap($promises)
* rejects, the returned promise is rejected with the rejection reason.
*
* @param mixed $promises Promises or values.
* @param bool $recursive - If true, resolves new promises that might have been added to the stack during its own resolution.
*
* @return PromiseInterface
*/
function all($promises, $recursive = false)
function all($promises)
{
$results = [];
$promise = \GuzzleHttp\Promise\each(
return each(
$promises,
function ($value, $idx) use (&$results) {
$results[$idx] = $value;
......@@ -232,19 +231,6 @@ function all($promises, $recursive = false)
ksort($results);
return $results;
});
if (true === $recursive) {
$promise = $promise->then(function ($results) use ($recursive, &$promises) {
foreach ($promises AS $promise) {
if (\GuzzleHttp\Promise\PromiseInterface::PENDING === $promise->getState()) {
return all($promises, $recursive);
}
}
return $results;
});
}
return $promise;
}
/**
......@@ -255,7 +241,7 @@ function all($promises, $recursive = false)
* fulfilled with an array that contains the fulfillment values of the winners
* in order of resolution.
*
* This promise is rejected with a {@see GuzzleHttp\Promise\AggregateException}
* This prommise is rejected with a {@see GuzzleHttp\Promise\AggregateException}
* if the number of fulfilled promises is less than the desired $count.
*
* @param int $count Total number of promises.
......@@ -268,7 +254,7 @@ function some($count, $promises)
$results = [];
$rejections = [];
return \GuzzleHttp\Promise\each(
return each(
$promises,
function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
if ($p->getState() !== PromiseInterface::PENDING) {
......@@ -324,7 +310,7 @@ function settle($promises)
{
$results = [];
return \GuzzleHttp\Promise\each(
return each(
$promises,
function ($value, $idx) use (&$results) {
$results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
......
......@@ -2,9 +2,8 @@
namespace GuzzleHttp\Promise\Tests;
use GuzzleHttp\Promise\AggregateException;
use PHPUnit\Framework\TestCase;
class AggregateExceptionTest extends TestCase
class AggregateExceptionTest extends \PHPUnit_Framework_TestCase
{
public function testHasReason()
{
......
......@@ -4,10 +4,10 @@ namespace GuzzleHttp\Promise\Tests;
use GuzzleHttp\Promise\Coroutine;
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\PromiseInterface;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_TestCase;
use ReflectionClass;
class CoroutineTest extends TestCase
class CoroutineTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider promiseInterfaceMethodProvider
......
......@@ -7,12 +7,11 @@ use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Promise\EachPromise;
use GuzzleHttp\Promise as P;
use PHPUnit\Framework\TestCase;
/**
* @covers GuzzleHttp\Promise\EachPromise
*/
class EachPromiseTest extends TestCase
class EachPromiseTest extends \PHPUnit_Framework_TestCase
{
public function testReturnsSameInstance()
{
......@@ -20,15 +19,6 @@ class EachPromiseTest extends TestCase
$this->assertSame($each->promise(), $each->promise());
}
public function testResolvesInCaseOfAnEmptyList()
{
$promises = [];
$each = new EachPromise($promises);
$p = $each->promise();
$this->assertNull($p->wait());
$this->assertEquals(PromiseInterface::FULFILLED, $p->getState());
}
public function testInvokesAllPromises()
{
$promises = [new Promise(), new Promise(), new Promise()];
......@@ -167,23 +157,13 @@ class EachPromiseTest extends TestCase
public function testCanBeCancelled()
{
$called = false;
$a = new FulfilledPromise('a');
$b = new Promise(function () use (&$called) { $called = true; });
$each = new EachPromise([$a, $b], [
'fulfilled' => function ($value, $idx, Promise $aggregate) {
$aggregate->cancel();
},
'rejected' => function ($reason) use (&$called) {
$called = true;
},
]);
$p = $each->promise();
$p->wait(false);
$this->assertEquals(PromiseInterface::FULFILLED, $a->getState());
$this->assertEquals(PromiseInterface::PENDING, $b->getState());
$this->assertEquals(PromiseInterface::REJECTED, $p->getState());
$this->assertFalse($called);
$this->markTestIncomplete();
}
public function testFulfillsImmediatelyWhenGivenAnEmptyIterator()
{
$each = new EachPromise(new \ArrayIterator([]));
$result = $each->promise()->wait();
}
public function testDoesNotBlowStackWithFulfilledPromises()
......@@ -255,7 +235,7 @@ class EachPromiseTest extends TestCase
$received = null;
$p->then(null, function ($reason) use (&$e) { $e = $reason; });
P\queue()->run();
$this->assertInstanceOf(\Exception::class, $e);
$this->assertInstanceOf('Exception', $e);
$this->assertEquals('Failure', $e->getMessage());
}
......@@ -353,27 +333,4 @@ class EachPromiseTest extends TestCase
$each->promise()->wait();
$this->assertCount(20, $results);
}
public function testIteratorWithSameKey()
{
$iter = function () {
yield 'foo' => $this->createSelfResolvingPromise(1);
yield 'foo' => $this->createSelfResolvingPromise(2);
yield 1 => $this->createSelfResolvingPromise(3);
yield 1 => $this->createSelfResolvingPromise(4);
};
$called = 0;
$each = new EachPromise($iter(), [
'fulfilled' => function ($value, $idx, Promise $aggregate) use (&$called) {
$called++;
if ($value < 3) {
$this->assertSame('foo', $idx);
} else {
$this->assertSame(1, $idx);
}
},
]);
$each->promise()->wait();
$this->assertSame(4, $called);
}
}
......@@ -3,12 +3,11 @@ namespace GuzzleHttp\Tests\Promise;
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\FulfilledPromise;
use PHPUnit\Framework\TestCase;
/**
* @covers GuzzleHttp\Promise\FulfilledPromise
*/
class FulfilledPromiseTest extends TestCase
class FulfilledPromiseTest extends \PHPUnit_Framework_TestCase
{
public function testReturnsValueWhenWaitedUpon()
{
......@@ -49,7 +48,6 @@ class FulfilledPromiseTest extends TestCase
{
$p = new FulfilledPromise('foo');
$p->resolve('foo');
$this->assertSame('foo', $p->wait());
}
/**
......
......@@ -3,16 +3,14 @@ namespace GuzzleHttp\Promise\Tests;
use GuzzleHttp\Promise\CancellationException;
use GuzzleHttp\Promise as P;
use GuzzleHttp\Promise\FulfilledPromise;
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\RejectedPromise;
use GuzzleHttp\Promise\RejectionException;
use PHPUnit\Framework\TestCase;
/**
* @covers GuzzleHttp\Promise\Promise
*/
class PromiseTest extends TestCase
class PromiseTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException \LogicException
......@@ -31,7 +29,6 @@ class PromiseTest extends TestCase
$p = new Promise();
$p->resolve('foo');
$p->resolve('foo');
$this->assertSame('foo', $p->wait());
}
/**
......@@ -51,7 +48,6 @@ class PromiseTest extends TestCase
$p = new Promise();
$p->reject('foo');
$p->reject('foo');
$this->assertSame('rejected', $p->getState());
}
/**
......@@ -73,7 +69,6 @@ class PromiseTest extends TestCase
/**
* @expectedException \GuzzleHttp\Promise\RejectionException
* @expectedExceptionMessage The promise was rejected with reason: Invoking the wait callback did not resolve the promise
*/
public function testRejectsAndThrowsWhenWaitFailsToResolve()
{
......@@ -314,7 +309,7 @@ class PromiseTest extends TestCase
$p->resolve('foo');
$p2 = $p->then();
$this->assertNotSame($p, $p2);
$this->assertInstanceOf(FulfilledPromise::class, $p2);
$this->assertInstanceOf('GuzzleHttp\Promise\FulfilledPromise', $p2);
}
public function testCreatesPromiseWhenRejectedAfterThen()
......@@ -346,7 +341,7 @@ class PromiseTest extends TestCase
$p->reject('foo');
$p2 = $p->then();
$this->assertNotSame($p, $p2);
$this->assertInstanceOf(RejectedPromise::class, $p2);
$this->assertInstanceOf('GuzzleHttp\Promise\RejectedPromise', $p2);
}
public function testInvokesWaitFnsForThens()
......
......@@ -3,12 +3,11 @@ namespace GuzzleHttp\Promise\Tests;
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\RejectedPromise;
use PHPUnit\Framework\TestCase;
/**
* @covers GuzzleHttp\Promise\RejectedPromise
*/
class RejectedPromiseTest extends TestCase
class RejectedPromiseTest extends \PHPUnit_Framework_TestCase
{
public function testThrowsReasonWhenWaitedUpon()
{
......@@ -54,7 +53,6 @@ class RejectedPromiseTest extends TestCase
{
$p = new RejectedPromise('foo');
$p->reject('foo');
$this->assertSame('rejected', $p->getState());
}
public function testThrowsSpecificException()
......@@ -112,7 +110,6 @@ class RejectedPromiseTest extends TestCase
{
$p = new RejectedPromise('a');
$p->wait(false);
$this->assertSame('rejected', $p->getState());
}
public function testOtherwiseIsSugarForRejections()
......
......@@ -2,7 +2,6 @@
namespace GuzzleHttp\Promise\Tests;
use GuzzleHttp\Promise\RejectionException;
use PHPUnit\Framework\TestCase;
class Thing1
{
......@@ -28,7 +27,7 @@ class Thing2 implements \JsonSerializable
/**
* @covers GuzzleHttp\Promise\RejectionException
*/
class RejectionExceptionTest extends TestCase
class RejectionExceptionTest extends \PHPUnit_Framework_TestCase
{
public function testCanGetReasonFromException()
{
......
......@@ -2,9 +2,8 @@
namespace GuzzleHttp\Promise\Test;
use GuzzleHttp\Promise\TaskQueue;
use PHPUnit\Framework\TestCase;
class TaskQueueTest extends TestCase
class TaskQueueTest extends \PHPUnit_Framework_TestCase
{
public function testKnowsIfEmpty()
{
......
<?php
require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/Thennable.php';
require __DIR__ . '/NotPromiseInstance.php';
......@@ -2,35 +2,30 @@
namespace GuzzleHttp\Promise\Tests;
use GuzzleHttp\Promise as P;
use GuzzleHttp\Promise\AggregateException;
use GuzzleHttp\Promise\FulfilledPromise;
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Promise\RejectedPromise;
use GuzzleHttp\Promise\RejectionException;
use GuzzleHttp\Promise\TaskQueue;
use PHPUnit\Framework\TestCase;
class FunctionsTest extends TestCase
class FunctionsTest extends \PHPUnit_Framework_TestCase
{
public function testCreatesPromiseForValue()
{
$p = P\promise_for('foo');
$this->assertInstanceOf(FulfilledPromise::class, $p);
$p = \GuzzleHttp\Promise\promise_for('foo');
$this->assertInstanceOf('GuzzleHttp\Promise\FulfilledPromise', $p);
}
public function testReturnsPromiseForPromise()
{
$p = new Promise();
$this->assertSame($p, P\promise_for($p));
$this->assertSame($p, \GuzzleHttp\Promise\promise_for($p));
}
public function testReturnsPromiseForThennable()
{
$p = new Thennable();
$wrapped = P\promise_for($p);
$wrapped = \GuzzleHttp\Promise\promise_for($p);
$this->assertNotSame($p, $wrapped);
$this->assertInstanceOf(PromiseInterface::class, $wrapped);
$this->assertInstanceOf('GuzzleHttp\Promise\PromiseInterface', $wrapped);
$p->resolve('foo');
P\queue()->run();
$this->assertEquals('foo', $wrapped->wait());
......@@ -38,15 +33,15 @@ class FunctionsTest extends TestCase
public function testReturnsRejection()
{
$p = P\rejection_for('fail');
$this->assertInstanceOf(RejectedPromise::class, $p);
$p = \GuzzleHttp\Promise\rejection_for('fail');
$this->assertInstanceOf('GuzzleHttp\Promise\RejectedPromise', $p);
$this->assertEquals('fail', $this->readAttribute($p, 'reason'));
}
public function testReturnsPromisesAsIsInRejectionFor()
{
$a = new Promise();
$b = P\rejection_for($a);
$b = \GuzzleHttp\Promise\rejection_for($a);
$this->assertSame($a, $b);
}
......@@ -56,7 +51,7 @@ class FunctionsTest extends TestCase
$a = new Promise(function () use (&$a) { $a->resolve('a'); });
$b = new Promise(function () use (&$b) { $b->reject('b'); });
$c = new Promise(function () use (&$c, $e) { $c->reject($e); });
$results = P\inspect_all([$a, $b, $c]);
$results = \GuzzleHttp\Promise\inspect_all([$a, $b, $c]);
$this->assertEquals([
['state' => 'fulfilled', 'value' => 'a'],
['state' => 'rejected', 'reason' => 'b'],
......@@ -70,13 +65,13 @@ class FunctionsTest extends TestCase
public function testUnwrapsPromisesWithNoDefaultAndFailure()
{
$promises = [new FulfilledPromise('a'), new Promise()];
P\unwrap($promises);
\GuzzleHttp\Promise\unwrap($promises);
}
public function testUnwrapsPromisesWithNoDefault()
{
$promises = [new FulfilledPromise('a')];
$this->assertEquals(['a'], P\unwrap($promises));
$this->assertEquals(['a'], \GuzzleHttp\Promise\unwrap($promises));
}
public function testUnwrapsPromisesWithKeys()
......@@ -88,7 +83,7 @@ class FunctionsTest extends TestCase
$this->assertEquals([
'foo' => 'a',
'bar' => 'b'
], P\unwrap($promises));
], \GuzzleHttp\Promise\unwrap($promises));
}
public function testAllAggregatesSortedArray()
......@@ -96,7 +91,7 @@ class FunctionsTest extends TestCase
$a = new Promise();
$b = new Promise();
$c = new Promise();
$d = P\all([$a, $b, $c]);
$d = \GuzzleHttp\Promise\all([$a, $b, $c]);
$b->resolve('b');
$a->resolve('a');
$c->resolve('c');
......@@ -108,31 +103,12 @@ class FunctionsTest extends TestCase
$this->assertEquals(['a', 'b', 'c'], $result);
}
public function testPromisesDynamicallyAddedToStack()
{
$promises = new \ArrayIterator();
$counter = 0;
$promises['a'] = new FulfilledPromise('a');
$promises['b'] = $promise = new Promise(function () use (&$promise, &$promises, &$counter) {
$counter++; // Make sure the wait function is called only once
$promise->resolve('b');
$promises['c'] = $subPromise = new Promise(function () use (&$subPromise) {
$subPromise->resolve('c');
});
});
$result = P\all($promises, true)->wait();
$this->assertCount(3, $promises);
$this->assertCount(3, $result);
$this->assertEquals($result['c'], 'c');
$this->assertSame(1, $counter);
}
public function testAllThrowsWhenAnyRejected()
{
$a = new Promise();
$b = new Promise();
$c = new Promise();
$d = P\all([$a, $b, $c]);
$d = \GuzzleHttp\Promise\all([$a, $b, $c]);
$b->resolve('b');
$a->reject('fail');
$c->resolve('c');
......@@ -149,7 +125,7 @@ class FunctionsTest extends TestCase
$a = new Promise();
$b = new Promise();
$c = new Promise();
$d = P\some(2, [$a, $b, $c]);
$d = \GuzzleHttp\Promise\some(2, [$a, $b, $c]);
$b->resolve('b');
$c->resolve('c');
$a->resolve('a');
......@@ -162,7 +138,7 @@ class FunctionsTest extends TestCase
{
$a = new Promise();
$b = new Promise();
$d = P\some(2, [$a, $b]);
$d = \GuzzleHttp\Promise\some(2, [$a, $b]);
$a->reject('bad');
$b->resolve('good');
P\queue()->run();
......@@ -171,7 +147,7 @@ class FunctionsTest extends TestCase
$called = $reason;
});
P\queue()->run();
$this->assertInstanceOf(AggregateException::class, $called);
$this->assertInstanceOf('GuzzleHttp\Promise\AggregateException', $called);
$this->assertContains('bad', $called->getReason());
}
......@@ -180,7 +156,7 @@ class FunctionsTest extends TestCase
$a = new Promise(function () use (&$a) { $a->resolve('a'); });
$b = new Promise(function () use (&$b) { $b->resolve('b'); });
$c = new Promise(function () use (&$c) { $c->resolve('c'); });
$d = P\some(2, [$a, $b, $c]);
$d = \GuzzleHttp\Promise\some(2, [$a, $b, $c]);
$this->assertEquals(['a', 'b'], $d->wait());
}
......@@ -191,7 +167,7 @@ class FunctionsTest extends TestCase
public function testThrowsIfImpossibleToWaitForSomeCount()
{
$a = new Promise(function () use (&$a) { $a->resolve('a'); });
$d = P\some(2, [$a]);
$d = \GuzzleHttp\Promise\some(2, [$a]);
$d->wait();
}
......@@ -203,7 +179,7 @@ class FunctionsTest extends TestCase
{
$a = new Promise();
$b = new Promise();
$d = P\some(3, [$a, $b]);
$d = \GuzzleHttp\Promise\some(3, [$a, $b]);
$a->resolve('a');
$b->resolve('b');
$d->wait();
......@@ -213,7 +189,7 @@ class FunctionsTest extends TestCase
{
$a = new Promise();
$b = new Promise();
$c = P\any([$a, $b]);
$c = \GuzzleHttp\Promise\any([$a, $b]);
$b->resolve('b');
$a->resolve('a');
//P\queue()->run();
......@@ -228,7 +204,7 @@ class FunctionsTest extends TestCase
$a = new Promise();
$b = new Promise();
$c = new Promise();
$d = P\settle([$a, $b, $c]);
$d = \GuzzleHttp\Promise\settle([$a, $b, $c]);
$b->resolve('b');
$c->resolve('c');
$a->reject('a');
......@@ -249,7 +225,7 @@ class FunctionsTest extends TestCase
$this->assertEquals([
'state' => 'fulfilled',
'value' => 'foo'
], P\inspect($p));
], \GuzzleHttp\Promise\inspect($p));
}
public function testCanInspectRejectedPromise()
......@@ -258,7 +234,7 @@ class FunctionsTest extends TestCase
$this->assertEquals([
'state' => 'rejected',
'reason' => 'foo'
], P\inspect($p));
], \GuzzleHttp\Promise\inspect($p));
}
public function testCanInspectRejectedPromiseWithNormalException()
......@@ -268,13 +244,13 @@ class FunctionsTest extends TestCase
$this->assertEquals([
'state' => 'rejected',
'reason' => $e
], P\inspect($p));
], \GuzzleHttp\Promise\inspect($p));
}
public function testCallsEachLimit()
{
$p = new Promise();
$aggregate = P\each_limit($p, 2);
$aggregate = \GuzzleHttp\Promise\each_limit($p, 2);
$p->resolve('a');
P\queue()->run();
$this->assertEquals($p::FULFILLED, $aggregate->getState());
......@@ -283,17 +259,17 @@ class FunctionsTest extends TestCase
public function testEachLimitAllRejectsOnFailure()
{
$p = [new FulfilledPromise('a'), new RejectedPromise('b')];
$aggregate = P\each_limit_all($p, 2);
$aggregate = \GuzzleHttp\Promise\each_limit_all($p, 2);
P\queue()->run();
$this->assertEquals(PromiseInterface::REJECTED, $aggregate->getState());
$result = P\inspect($aggregate);
$this->assertEquals(P\PromiseInterface::REJECTED, $aggregate->getState());
$result = \GuzzleHttp\Promise\inspect($aggregate);
$this->assertEquals('b', $result['reason']);
}
public function testIterForReturnsIterator()
{
$iter = new \ArrayIterator();
$this->assertSame($iter, P\iter_for($iter));
$this->assertSame($iter, \GuzzleHttp\Promise\iter_for($iter));
}
public function testKnowsIfFulfilled()
......@@ -320,7 +296,7 @@ class FunctionsTest extends TestCase
public function testReturnsTrampoline()
{
$this->assertInstanceOf(TaskQueue::class, P\queue());
$this->assertInstanceOf('GuzzleHttp\Promise\TaskQueue', P\queue());
$this->assertSame(P\queue(), P\queue());
}
......@@ -357,7 +333,7 @@ class FunctionsTest extends TestCase
public function testYieldsFromCoroutine()
{
$promise = P\coroutine(function () {
$value = (yield new FulfilledPromise('a'));
$value = (yield new P\FulfilledPromise('a'));
yield $value . 'b';
});
$promise->then(function ($value) use (&$result) { $result = $value; });
......@@ -369,67 +345,54 @@ class FunctionsTest extends TestCase
{
$promise = P\coroutine(function () {
try {
yield new RejectedPromise('a');
yield new P\RejectedPromise('a');
$this->fail('Should have thrown into the coroutine!');
} catch (RejectionException $e) {
$value = (yield new FulfilledPromise($e->getReason()));
} catch (P\RejectionException $e) {
$value = (yield new P\FulfilledPromise($e->getReason()));
yield $value . 'b';
}
});
$promise->then(function ($value) use (&$result) { $result = $value; });
P\queue()->run();
$this->assertEquals(PromiseInterface::FULFILLED, $promise->getState());
$this->assertEquals(P\PromiseInterface::FULFILLED, $promise->getState());
$this->assertEquals('ab', $result);
}
/**
* @dataProvider rejectsParentExceptionProvider
*/
public function testRejectsParentExceptionWhenException(PromiseInterface $promise)
public function testRejectsParentExceptionWhenException()
{
$promise = P\coroutine(function () {
yield new P\FulfilledPromise(0);
throw new \Exception('a');
});
$promise->then(
function () { $this->fail(); },
function ($reason) use (&$result) { $result = $reason; }
);
P\queue()->run();
$this->assertInstanceOf(\Exception::class, $result);
$this->assertInstanceOf('Exception', $result);
$this->assertEquals('a', $result->getMessage());
}
public function rejectsParentExceptionProvider()
{
return [
[ P\coroutine(function () {
yield new FulfilledPromise(0);
throw new \Exception('a');
}) ],
[ P\coroutine(function () {
throw new \Exception('a');
yield new FulfilledPromise(0);
}) ],
];
}
public function testCanRejectFromRejectionCallback()
{
$promise = P\coroutine(function () {
yield new FulfilledPromise(0);
yield new RejectedPromise('no!');
yield new P\FulfilledPromise(0);
yield new P\RejectedPromise('no!');
});
$promise->then(
function () { $this->fail(); },
function ($reason) use (&$result) { $result = $reason; }
);
P\queue()->run();
$this->assertInstanceOf(RejectionException::class, $result);
$this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $result);
$this->assertEquals('no!', $result->getReason());
}
public function testCanAsyncReject()
{
$rej = new Promise();
$rej = new P\Promise();
$promise = P\coroutine(function () use ($rej) {
yield new FulfilledPromise(0);
yield new P\FulfilledPromise(0);
yield $rej;
});
$promise->then(
......@@ -438,7 +401,7 @@ class FunctionsTest extends TestCase
);
$rej->reject('no!');
P\queue()->run();
$this->assertInstanceOf(RejectionException::class, $result);
$this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $result);
$this->assertEquals('no!', $result->getReason());
}
......@@ -446,15 +409,15 @@ class FunctionsTest extends TestCase
{
$promise = P\coroutine(function () {
try {
yield new RejectedPromise('a');
yield new P\RejectedPromise('a');
$this->fail('Should have thrown into the coroutine!');
} catch (RejectionException $e) {
} catch (P\RejectionException $e) {
throw new \Exception('foo');
}
});
$promise->otherwise(function ($value) use (&$result) { $result = $value; });
P\queue()->run();
$this->assertEquals(PromiseInterface::REJECTED, $promise->getState());
$this->assertEquals(P\PromiseInterface::REJECTED, $promise->getState());
$this->assertContains('foo', $result->getMessage());
}
......@@ -462,15 +425,15 @@ class FunctionsTest extends TestCase
{
$promise = P\coroutine(function () {
try {
yield new RejectedPromise('a');
yield new P\RejectedPromise('a');
$this->fail('Should have thrown into the coroutine!');
} catch (RejectionException $e) {
yield new RejectedPromise('foo');
} catch (P\RejectionException $e) {
yield new P\RejectedPromise('foo');
}
});
$promise->otherwise(function ($value) use (&$result) { $result = $value; });
P\queue()->run();
$this->assertEquals(PromiseInterface::REJECTED, $promise->getState());
$this->assertEquals(P\PromiseInterface::REJECTED, $promise->getState());
$this->assertContains('foo', $result->getMessage());
}
......@@ -479,7 +442,7 @@ class FunctionsTest extends TestCase
return P\coroutine(function () {
$value = 0;
for ($i = 0; $i < 1000; $i++) {
$value = (yield new FulfilledPromise($i));
$value = (yield new P\FulfilledPromise($i));
}
yield $value;
});
......@@ -508,12 +471,12 @@ class FunctionsTest extends TestCase
for ($i = 0; $i < 1000; $i++) {
try {
if ($i % 2) {
$value = (yield new FulfilledPromise($i));
$value = (yield new P\FulfilledPromise($i));
} else {
$value = (yield new RejectedPromise($i));
$value = (yield new P\RejectedPromise($i));
}
} catch (\Exception $e) {
$value = (yield new FulfilledPromise($i));
$value = (yield new P\FulfilledPromise($i));
}
}
yield $value;
......@@ -539,19 +502,21 @@ class FunctionsTest extends TestCase
public function testAsyncPromisesWithCorrectlyYieldedValues()
{
$promises = [
new Promise(),
new Promise(),
new Promise()
new P\Promise(),
new P\Promise(),
new P\Promise()
];
$promise = P\coroutine(function () use ($promises) {
$this->assertEquals('skip', (yield new FulfilledPromise('skip')));
$value = null;
$this->assertEquals('skip', (yield new P\FulfilledPromise('skip')));
foreach ($promises as $idx => $p) {
$this->assertEquals($idx, (yield $p));
$this->assertEquals('skip', (yield new FulfilledPromise('skip')));
$value = (yield $p);
$this->assertEquals($value, $idx);
$this->assertEquals('skip', (yield new P\FulfilledPromise('skip')));
}
$this->assertEquals('skip', (yield new FulfilledPromise('skip')));
yield 2;
$this->assertEquals('skip', (yield new P\FulfilledPromise('skip')));
yield $value;
});
$promises[0]->resolve(0);
......@@ -565,10 +530,10 @@ class FunctionsTest extends TestCase
public function testYieldFinalWaitablePromise()
{
$p1 = new Promise(function () use (&$p1) {
$p1 = new P\Promise(function () use (&$p1) {
$p1->resolve('skip me');
});
$p2 = new Promise(function () use (&$p2) {
$p2 = new P\Promise(function () use (&$p2) {
$p2->resolve('hello!');
});
$co = P\coroutine(function() use ($p1, $p2) {
......@@ -581,8 +546,8 @@ class FunctionsTest extends TestCase
public function testCanYieldFinalPendingPromise()
{
$p1 = new Promise();
$p2 = new Promise();
$p1 = new P\Promise();
$p2 = new P\Promise();
$co = P\coroutine(function() use ($p1, $p2) {
yield $p1;
yield $p2;
......@@ -596,11 +561,11 @@ class FunctionsTest extends TestCase
public function testCanNestYieldsAndFailures()
{
$p1 = new Promise();
$p2 = new Promise();
$p3 = new Promise();
$p4 = new Promise();
$p5 = new Promise();
$p1 = new P\Promise();
$p2 = new P\Promise();
$p3 = new P\Promise();
$p4 = new P\Promise();
$p5 = new P\Promise();
$co = P\coroutine(function() use ($p1, $p2, $p3, $p4, $p5) {
try {
yield $p1;
......@@ -628,7 +593,7 @@ class FunctionsTest extends TestCase
{
$promises = [];
for ($i = 0; $i < 20; $i++) {
$promises[] = new Promise();
$promises[] = new P\Promise();
}
$co = P\coroutine(function() use ($promises) {
......@@ -660,7 +625,7 @@ class FunctionsTest extends TestCase
$f = function () {
static $i = 0;
$i++;
return $p = new Promise(function () use (&$p, $i) {
return $p = new P\Promise(function () use (&$p, $i) {
$p->resolve($i . '-bar');
});
};
......@@ -671,7 +636,7 @@ class FunctionsTest extends TestCase
}
$p = P\coroutine(function () use ($promises) {
yield new FulfilledPromise('foo!');
yield new P\FulfilledPromise('foo!');
foreach ($promises as $promise) {
yield $promise;
}
......@@ -682,12 +647,12 @@ class FunctionsTest extends TestCase
public function testCanWaitOnErroredPromises()
{
$p1 = new Promise(function () use (&$p1) { $p1->reject('a'); });
$p2 = new Promise(function () use (&$p2) { $p2->resolve('b'); });
$p3 = new Promise(function () use (&$p3) { $p3->resolve('c'); });
$p4 = new Promise(function () use (&$p4) { $p4->reject('d'); });
$p5 = new Promise(function () use (&$p5) { $p5->resolve('e'); });
$p6 = new Promise(function () use (&$p6) { $p6->reject('f'); });
$p1 = new P\Promise(function () use (&$p1) { $p1->reject('a'); });
$p2 = new P\Promise(function () use (&$p2) { $p2->resolve('b'); });
$p3 = new P\Promise(function () use (&$p3) { $p3->resolve('c'); });
$p4 = new P\Promise(function () use (&$p4) { $p4->reject('d'); });
$p5 = new P\Promise(function () use (&$p5) { $p5->resolve('e'); });
$p6 = new P\Promise(function () use (&$p6) { $p6->reject('f'); });
$co = P\coroutine(function() use ($p1, $p2, $p3, $p4, $p5, $p6) {
try {
......@@ -710,8 +675,8 @@ class FunctionsTest extends TestCase
public function testCoroutineOtherwiseIntegrationTest()
{
$a = new Promise();
$b = new Promise();
$a = new P\Promise();
$b = new P\Promise();
$promise = P\coroutine(function () use ($a, $b) {
// Execute the pool of commands concurrently, and process errors.
yield $a;
......@@ -723,7 +688,7 @@ class FunctionsTest extends TestCase
$a->resolve('a');
$b->reject('b');
$reason = P\inspect($promise)['reason'];
$this->assertInstanceOf(\OutOfBoundsException::class, $reason);
$this->assertInstanceOf(RejectionException::class, $reason->getPrevious());
$this->assertInstanceOf('OutOfBoundsException', $reason);
$this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $reason->getPrevious());
}
}
language: php
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
- 7.4
- hhvm
matrix:
# See https://travis-ci.community/t/php-5-4-and-5-5-archives-missing/3723
include:
- php: 5.4
dist: trusty
- php: 5.5
dist: trusty
fast_finish: true
allow_failures:
- php: hhvm
......
......@@ -519,15 +519,6 @@ Determines the mimetype of a file by looking at its extension.
Maps a file extensions to a mimetype.
## `function get_message_body_summary`
`function get_message_body_summary(MessageInterface $message, $truncateAt = 120)`
Get a short summary of the message body.
Will return `null` if the response is not printable.
# Additional URI Methods
Aside from the standard `Psr\Http\Message\UriInterface` implementation in form of the `GuzzleHttp\Psr7\Uri` class,
......
......@@ -28,7 +28,7 @@
"psr/http-message-implementation": "1.0"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
},
"autoload": {
"psr-4": {
......
......@@ -194,7 +194,7 @@ trait MessageTrait
}
return trim((string) $value, " \t");
}, array_values($values));
}, $values);
}
private function assertHeader($header)
......
......@@ -76,10 +76,8 @@ class Stream implements StreamInterface
public function __toString()
{
try {
if ($this->isSeekable()) {
$this->seek(0);
}
return $this->getContents();
$this->seek(0);
return (string) stream_get_contents($this->stream);
} catch (\Exception $e) {
return '';
}
......@@ -195,7 +193,7 @@ class Stream implements StreamInterface
public function seek($offset, $whence = SEEK_SET)
{
$whence = (int) $whence;
if (!isset($this->stream)) {
throw new \RuntimeException('Stream is detached');
}
......
......@@ -33,13 +33,7 @@ function str(MessageInterface $message)
}
foreach ($message->getHeaders() as $name => $values) {
if (strtolower($name) === 'set-cookie') {
foreach ($values as $value) {
$msg .= "\r\n{$name}: " . $value;
}
} else {
$msg .= "\r\n{$name}: " . implode(', ', $values);
}
$msg .= "\r\n{$name}: " . implode(', ', $values);
}
return "{$msg}\r\n\r\n" . $message->getBody();
......@@ -847,7 +841,7 @@ function _parse_request_uri($path, array $headers)
}
/**
* Get a short summary of the message body.
* Get a short summary of the message body
*
* Will return `null` if the response is not printable.
*
......
......@@ -598,17 +598,6 @@ class FunctionsTest extends BaseTest
);
}
public function testCorrectlyRendersSetCookieHeadersToString()
{
$response = new Psr7\Response(200, [
'Set-Cookie' => ['bar','baz','qux']
], 'hello', '1.0', 'FOO');
$this->assertEquals(
"HTTP/1.0 200 FOO\r\nSet-Cookie: bar\r\nSet-Cookie: baz\r\nSet-Cookie: qux\r\n\r\nhello",
Psr7\str($response)
);
}
public function parseParamsProvider()
{
$res1 = [
......
......@@ -299,15 +299,6 @@ class ResponseTest extends BaseTest
}
}
public function testWithAddedHeaderArrayValueAndKeys()
{
$message = (new Response())->withAddedHeader('list', ['foo' => 'one']);
$message = $message->withAddedHeader('list', ['foo' => 'two', 'bar' => 'three']);
$headerLine = $message->getHeaderLine('list');
$this->assertSame('one, two, three', $headerLine);
}
/**
* @dataProvider nonIntegerStatusCodeProvider
* @param mixed $invalidValues
......
......@@ -67,24 +67,6 @@ class StreamTest extends BaseTest
$stream->close();
}
public function testConvertsToStringNonSeekableStream()
{
$handle = popen('echo foo', 'r');
$stream = new Stream($handle);
$this->assertFalse($stream->isSeekable());
$this->assertSame('foo', trim((string) $stream));
}
public function testConvertsToStringNonSeekablePartiallyReadStream()
{
$handle = popen('echo bar', 'r');
$stream = new Stream($handle);
$firstLetter = $stream->read(1);
$this->assertFalse($stream->isSeekable());
$this->assertSame('b', $firstLetter);
$this->assertSame('ar', trim((string) $stream));
}
public function testGetsContents()
{
$handle = fopen('php://temp', 'w+');
......
......@@ -33,8 +33,8 @@ abstract class AbstractHandler implements HandlerInterface, ResettableInterface
protected $processors = array();
/**
* @param int|string $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($level = Logger::DEBUG, $bubble = true)
{
......
......@@ -52,7 +52,7 @@ class GitProcessor implements ProcessorInterface
}
$branches = `git branch -v --no-abbrev`;
if ($branches && preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
if (preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
return self::$cache = array(
'branch' => $matches[1],
'commit' => $matches[2],
......
......@@ -10,7 +10,4 @@ interface that describes a HTTP message. See the specification for more details.
Usage
-----
Before reading the usage guide we recommend reading the PSR-7 interfaces method list:
* [`PSR-7 Interfaces Method List`](docs/PSR7-Interfaces.md)
* [`PSR-7 Usage Guide`](docs/PSR7-Usage.md)
\ No newline at end of file
We'll certainly need some stuff in here.
\ No newline at end of file
# Interfaces
The purpose of this list is to help in finding the methods when working with PSR-7. This can be considered as a cheatsheet for PSR-7 interfaces.
The interfaces defined in PSR-7 are the following:
| Class Name | Description |
|---|---|
| [Psr\Http\Message\MessageInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagemessageinterface) | Representation of a HTTP message |
| [Psr\Http\Message\RequestInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagerequestinterface) | Representation of an outgoing, client-side request. |
| [Psr\Http\Message\ServerRequestInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageserverrequestinterface) | Representation of an incoming, server-side HTTP request. |
| [Psr\Http\Message\ResponseInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageresponseinterface) | Representation of an outgoing, server-side response. |
| [Psr\Http\Message\StreamInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagestreaminterface) | Describes a data stream |
| [Psr\Http\Message\UriInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageuriinterface) | Value object representing a URI. |
| [Psr\Http\Message\UploadedFileInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageuploadedfileinterface) | Value object representing a file uploaded through an HTTP request. |
## `Psr\Http\Message\MessageInterface` Methods
| Method Name | Description | Notes |
|------------------------------------| ----------- | ----- |
| `getProtocolVersion()` | Retrieve HTTP protocol version | 1.0 or 1.1 |
| `withProtocolVersion($version)` | Returns new message instance with given HTTP protocol version | |
| `getHeaders()` | Retrieve all HTTP Headers | [Request Header List](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields), [Response Header List](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Response_fields) |
| `hasHeader($name)` | Checks if HTTP Header with given name exists | |
| `getHeader($name)` | Retrieves a array with the values for a single header | |
| `getHeaderLine($name)` | Retrieves a comma-separated string of the values for a single header | |
| `withHeader($name, $value)` | Returns new message instance with given HTTP Header | if the header existed in the original instance, replaces the header value from the original message with the value provided when creating the new instance. |
| `withAddedHeader($name, $value)` | Returns new message instance with appended value to given header | If header already exists value will be appended, if not a new header will be created |
| `withoutHeader($name)` | Removes HTTP Header with given name| |
| `getBody()` | Retrieves the HTTP Message Body | Returns object implementing `StreamInterface`|
| `withBody(StreamInterface $body)` | Returns new message instance with given HTTP Message Body | |
## `Psr\Http\Message\RequestInterface` Methods
Same methods as `Psr\Http\Message\MessageInterface` + the following methods:
| Method Name | Description | Notes |
|------------------------------------| ----------- | ----- |
| `getRequestTarget()` | Retrieves the message's request target | origin-form, absolute-form, authority-form, asterisk-form ([RFC7230](https://www.rfc-editor.org/rfc/rfc7230.txt)) |
| `withRequestTarget($requestTarget)` | Return a new message instance with the specific request-target | |
| `getMethod()` | Retrieves the HTTP method of the request. | GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE (defined in [RFC7231](https://tools.ietf.org/html/rfc7231)), PATCH (defined in [RFC5789](https://tools.ietf.org/html/rfc5789)) |
| `withMethod($method)` | Returns a new message instance with the provided HTTP method | |
| `getUri()` | Retrieves the URI instance | |
| `withUri(UriInterface $uri, $preserveHost = false)` | Returns a new message instance with the provided URI | |
## `Psr\Http\Message\ServerRequestInterface` Methods
Same methods as `Psr\Http\Message\RequestInterface` + the following methods:
| Method Name | Description | Notes |
|------------------------------------| ----------- | ----- |
| `getServerParams() ` | Retrieve server parameters | Typically derived from `$_SERVER` |
| `getCookieParams()` | Retrieves cookies sent by the client to the server. | Typically derived from `$_COOKIES` |
| `withCookieParams(array $cookies)` | Returns a new request instance with the specified cookies | |
| `withQueryParams(array $query)` | Returns a new request instance with the specified query string arguments | |
| `getUploadedFiles()` | Retrieve normalized file upload data | |
| `withUploadedFiles(array $uploadedFiles)` | Returns a new request instance with the specified uploaded files | |
| `getParsedBody()` | Retrieve any parameters provided in the request body | |
| `withParsedBody($data)` | Returns a new request instance with the specified body parameters | |
| `getAttributes()` | Retrieve attributes derived from the request | |
| `getAttribute($name, $default = null)` | Retrieve a single derived request attribute | |
| `withAttribute($name, $value)` | Returns a new request instance with the specified derived request attribute | |
| `withoutAttribute($name)` | Returns a new request instance that without the specified derived request attribute | |
## `Psr\Http\Message\ResponseInterface` Methods:
Same methods as `Psr\Http\Message\MessageInterface` + the following methods:
| Method Name | Description | Notes |
|------------------------------------| ----------- | ----- |
| `getStatusCode()` | Gets the response status code. | |
| `withStatus($code, $reasonPhrase = '')` | Returns a new response instance with the specified status code and, optionally, reason phrase. | |
| `getReasonPhrase()` | Gets the response reason phrase associated with the status code. | |
## `Psr\Http\Message\StreamInterface` Methods
| Method Name | Description | Notes |
|------------------------------------| ----------- | ----- |
| `__toString()` | Reads all data from the stream into a string, from the beginning to end. | |
| `close()` | Closes the stream and any underlying resources. | |
| `detach()` | Separates any underlying resources from the stream. | |
| `getSize()` | Get the size of the stream if known. | |
| `eof()` | Returns true if the stream is at the end of the stream.| |
| `isSeekable()` | Returns whether or not the stream is seekable. | |
| `seek($offset, $whence = SEEK_SET)` | Seek to a position in the stream. | |
| `rewind()` | Seek to the beginning of the stream. | |
| `isWritable()` | Returns whether or not the stream is writable. | |
| `write($string)` | Write data to the stream. | |
| `isReadable()` | Returns whether or not the stream is readable. | |
| `read($length)` | Read data from the stream. | |
| `getContents()` | Returns the remaining contents in a string | |
| `getMetadata($key = null)()` | Get stream metadata as an associative array or retrieve a specific key. | |
## `Psr\Http\Message\UriInterface` Methods
| Method Name | Description | Notes |
|------------------------------------| ----------- | ----- |
| `getScheme()` | Retrieve the scheme component of the URI. | |
| `getAuthority()` | Retrieve the authority component of the URI. | |
| `getUserInfo()` | Retrieve the user information component of the URI. | |
| `getHost()` | Retrieve the host component of the URI. | |
| `getPort()` | Retrieve the port component of the URI. | |
| `getPath()` | Retrieve the path component of the URI. | |
| `getQuery()` | Retrieve the query string of the URI. | |
| `getFragment()` | Retrieve the fragment component of the URI. | |
| `withScheme($scheme)` | Return an instance with the specified scheme. | |
| `withUserInfo($user, $password = null)` | Return an instance with the specified user information. | |
| `withHost($host)` | Return an instance with the specified host. | |
| `withPort($port)` | Return an instance with the specified port. | |
| `withPath($path)` | Return an instance with the specified path. | |
| `withQuery($query)` | Return an instance with the specified query string. | |
| `withFragment($fragment)` | Return an instance with the specified URI fragment. | |
| `__toString()` | Return the string representation as a URI reference. | |
## `Psr\Http\Message\UploadedFileInterface` Methods
| Method Name | Description | Notes |
|------------------------------------| ----------- | ----- |
| `getStream()` | Retrieve a stream representing the uploaded file. | |
| `moveTo($targetPath)` | Move the uploaded file to a new location. | |
| `getSize()` | Retrieve the file size. | |
| `getError()` | Retrieve the error associated with the uploaded file. | |
| `getClientFilename()` | Retrieve the filename sent by the client. | |
| `getClientMediaType()` | Retrieve the media type sent by the client. | |
> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`.
> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered.
### PSR-7 Usage
All PSR-7 applications comply with these interfaces
They were created to establish a standard between middleware implementations.
> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`.
> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered.
The following examples will illustrate how basic operations are done in PSR-7.
##### Examples
For this examples to work (at least) a PSR-7 implementation package is required. (eg: zendframework/zend-diactoros, guzzlehttp/psr7, slim/slim, etc)
All PSR-7 implementations should have the same behaviour.
The following will be assumed:
`$request` is an object of `Psr\Http\Message\RequestInterface` and
`$response` is an object implementing `Psr\Http\Message\RequestInterface`
### Working with HTTP Headers
#### Adding headers to response:
```php
$response->withHeader('My-Custom-Header', 'My Custom Message');
```
#### Appending values to headers
```php
$response->withAddedHeader('My-Custom-Header', 'The second message');
```
#### Checking if header exists:
```php
$request->hasHeader('My-Custom-Header'); // will return false
$response->hasHeader('My-Custom-Header'); // will return true
```
> Note: My-Custom-Header was only added in the Response
#### Getting comma-separated values from a header (also applies to request)
```php
// getting value from request headers
$request->getHeaderLine('Content-Type'); // will return: "text/html; charset=UTF-8"
// getting value from response headers
$response->getHeaderLine('My-Custom-Header'); // will return: "My Custom Message; The second message"
```
#### Getting array of value from a header (also applies to request)
```php
// getting value from request headers
$request->getHeader('Content-Type'); // will return: ["text/html", "charset=UTF-8"]
// getting value from response headers
$response->getHeader('My-Custom-Header'); // will return: ["My Custom Message", "The second message"]
```
#### Removing headers from HTTP Messages
```php
// removing a header from Request, removing deprecated "Content-MD5" header
$request->withoutHeader('Content-MD5');
// removing a header from Response
// effect: the browser won't know the size of the stream
// the browser will download the stream till it ends
$response->withoutHeader('Content-Length');
```
### Working with HTTP Message Body
When working with the PSR-7 there are two methods of implementation:
#### 1. Getting the body separately
> This method makes the body handling easier to understand and is useful when repeatedly calling body methods. (You only call `getBody()` once). Using this method mistakes like `$response->write()` are also prevented.
```php
$body = $response->getBody();
// operations on body, eg. read, write, seek
// ...
// replacing the old body
$response->withBody($body);
// this last statement is optional as we working with objects
// in this case the "new" body is same with the "old" one
// the $body variable has the same value as the one in $request, only the reference is passed
```
#### 2. Working directly on response
> This method is useful when only performing few operations as the `$request->getBody()` statement fragment is required
```php
$response->getBody()->write('hello');
```
### Getting the body contents
The following snippet gets the contents of a stream contents.
> Note: Streams must be rewinded, if content was written into streams, it will be ignored when calling `getContents()` because the stream pointer is set to the last character, which is `\0` - meaning end of stream.
```php
$body = $response->getBody();
$body->rewind(); // or $body->seek(0);
$bodyText = $body->getContents();
```
> Note: If `$body->seek(1)` is called before `$body->getContents()`, the first character will be ommited as the starting pointer is set to `1`, not `0`. This is why using `$body->rewind()` is recommended.
### Append to body
```php
$response->getBody()->write('Hello'); // writing directly
$body = $request->getBody(); // which is a `StreamInterface`
$body->write('xxxxx');
```
### Prepend to body
Prepending is different when it comes to streams. The content must be copied before writing the content to be prepended.
The following example will explain the behaviour of streams.
```php
// assuming our response is initially empty
$body = $repsonse->getBody();
// writing the string "abcd"
$body->write('abcd');
// seeking to start of stream
$body->seek(0);
// writing 'ef'
$body->write('ef'); // at this point the stream contains "efcd"
```
#### Prepending by rewriting separately
```php
// assuming our response body stream only contains: "abcd"
$body = $response->getBody();
$body->rewind();
$contents = $body->getContents(); // abcd
// seeking the stream to beginning
$body->rewind();
$body->write('ef'); // stream contains "efcd"
$body->write($contents); // stream contains "efabcd"
```
> Note: `getContents()` seeks the stream while reading it, therefore if the second `rewind()` method call was not present the stream would have resulted in `abcdefabcd` because the `write()` method appends to stream if not preceeded by `rewind()` or `seek(0)`.
#### Prepending by using contents as a string
```php
$body = $response->getBody();
$body->rewind();
$contents = $body->getContents(); // efabcd
$contents = 'ef'.$contents;
$body->rewind();
$body->write($contents);
```
......@@ -151,7 +151,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
$eventName = $swap;
if (!$event instanceof Event) {
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an instance of "%s", "%s" given.', EventDispatcherInterface::class, Event::class, \is_object($event) ? \get_class($event) : \gettype($event)));
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an instance of %s, %s given.', EventDispatcherInterface::class, Event::class, \is_object($event) ? \get_class($event) : \gettype($event)));
}
}
......
......@@ -60,7 +60,7 @@ class EventDispatcher implements EventDispatcherInterface
$event = $eventName ?? new Event();
$eventName = $swap;
} else {
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, "%s" given.', EventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event)));
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, %s given.', EventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event)));
}
if (null !== $this->optimized && null !== $eventName) {
......
......@@ -65,7 +65,7 @@ final class LegacyEventDispatcherProxy implements EventDispatcherInterface
$event = $eventName ?? new Event();
$eventName = $swap;
} else {
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, "%s" given.', ContractsEventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event)));
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, %s given.', ContractsEventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event)));
}
$listeners = $this->getListeners($eventName);
......
......@@ -11,9 +11,6 @@
namespace Symfony\Component\HttpFoundation;
// Help opcache.preload discover always-needed symbols
class_exists(AcceptHeaderItem::class);
/**
* Represents an Accept-* header.
*
......
......@@ -91,7 +91,7 @@ class File extends \SplFileInfo
$renamed = rename($this->getPathname(), $target);
restore_error_handler();
if (!$renamed) {
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error)));
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
}
@chmod($target, 0666 & ~umask());
......@@ -106,10 +106,10 @@ class File extends \SplFileInfo
{
if (!is_dir($directory)) {
if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) {
throw new FileException(sprintf('Unable to create the "%s" directory.', $directory));
throw new FileException(sprintf('Unable to create the "%s" directory', $directory));
}
} elseif (!is_writable($directory)) {
throw new FileException(sprintf('Unable to write in the "%s" directory.', $directory));
throw new FileException(sprintf('Unable to write in the "%s" directory', $directory));
}
$target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name));
......
......@@ -130,7 +130,7 @@ class MimeTypeGuesser implements MimeTypeGuesserInterface
}
if (2 === \count($this->guessers) && !FileBinaryMimeTypeGuesser::isSupported() && !FileinfoMimeTypeGuesser::isSupported()) {
throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?).');
throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)');
}
return null;
......
......@@ -208,7 +208,7 @@ class UploadedFile extends File
$moved = move_uploaded_file($this->getPathname(), $target);
restore_error_handler();
if (!$moved) {
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error)));
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
}
@chmod($target, 0666 & ~umask());
......
......@@ -219,7 +219,7 @@ class HeaderBag implements \IteratorAggregate, \Countable
}
if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) {
throw new \RuntimeException(sprintf('The "%s" HTTP header is not parseable (%s).', $key, $value));
throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value));
}
return $date;
......
......@@ -15,14 +15,6 @@ use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
// Help opcache.preload discover always-needed symbols
class_exists(AcceptHeader::class);
class_exists(FileBag::class);
class_exists(HeaderBag::class);
class_exists(HeaderUtils::class);
class_exists(ParameterBag::class);
class_exists(ServerBag::class);
/**
* Request represents an HTTP request.
*
......@@ -733,7 +725,7 @@ class Request
if (null === $session) {
@trigger_error(sprintf('Calling "%s()" when no session has been set is deprecated since Symfony 4.1 and will throw an exception in 5.0. Use "hasSession()" instead.', __METHOD__), E_USER_DEPRECATED);
// throw new \BadMethodCallException('Session has not been set.');
// throw new \BadMethodCallException('Session has not been set');
}
return $session;
......
......@@ -11,9 +11,6 @@
namespace Symfony\Component\HttpFoundation;
// Help opcache.preload discover always-needed symbols
class_exists(ResponseHeaderBag::class);
/**
* Response represents an HTTP response.
*
......
......@@ -252,13 +252,10 @@ class ResponseHeaderBag extends HeaderBag
* @param string $domain
* @param bool $secure
* @param bool $httpOnly
* @param string $sameSite
*/
public function clearCookie($name, $path = '/', $domain = null, $secure = false, $httpOnly = true/*, $sameSite = null*/)
public function clearCookie($name, $path = '/', $domain = null, $secure = false, $httpOnly = true)
{
$sameSite = \func_num_args() > 5 ? func_get_arg(5) : null;
$this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite));
$this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, null));
}
/**
......
......@@ -18,11 +18,6 @@ use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
// Help opcache.preload discover always-needed symbols
class_exists(AttributeBag::class);
class_exists(FlashBag::class);
class_exists(SessionBagProxy::class);
/**
* @author Fabien Potencier <fabien@symfony.com>
* @author Drak <drak@zikula.org>
......
......@@ -47,7 +47,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler
$this->memcached = $memcached;
if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime'])) {
throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff)));
throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff)));
}
$this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400;
......
......@@ -66,7 +66,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler
public function __construct(\MongoDB\Client $mongo, array $options)
{
if (!isset($options['database']) || !isset($options['collection'])) {
throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler.');
throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler');
}
$this->mongo = $mongo;
......
......@@ -38,7 +38,7 @@ class NativeFileSessionHandler extends \SessionHandler
if ($count = substr_count($savePath, ';')) {
if ($count > 2) {
throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'.', $savePath));
throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath));
}
// characters after last ';' are the path
......@@ -46,7 +46,7 @@ class NativeFileSessionHandler extends \SessionHandler
}
if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, true) && !is_dir($baseDir)) {
throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $baseDir));
throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $baseDir));
}
ini_set('session.save_path', $savePath);
......
......@@ -174,7 +174,7 @@ class PdoSessionHandler extends AbstractSessionHandler
{
if ($pdoOrDsn instanceof \PDO) {
if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) {
throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__));
throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__));
}
$this->pdo = $pdoOrDsn;
......@@ -468,7 +468,7 @@ class PdoSessionHandler extends AbstractSessionHandler
}
if (!isset($params['scheme'])) {
throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler.');
throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler');
}
$driverAliasMap = [
......
......@@ -54,11 +54,11 @@ class RedisSessionHandler extends AbstractSessionHandler
!$redis instanceof RedisProxy &&
!$redis instanceof RedisClusterProxy
) {
throw new \InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis)));
throw new \InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, %s given', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis)));
}
if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) {
throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff)));
throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff)));
}
$this->redis = $redis;
......
......@@ -27,7 +27,7 @@ class SessionHandlerFactory
public static function createHandler($connection): AbstractSessionHandler
{
if (!\is_string($connection) && !\is_object($connection)) {
throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a string or a connection object, "%s" given.', __METHOD__, \gettype($connection)));
throw new \TypeError(sprintf('Argument 1 passed to %s() must be a string or a connection object, %s given.', __METHOD__, \gettype($connection)));
}
switch (true) {
......@@ -46,7 +46,7 @@ class SessionHandlerFactory
return new PdoSessionHandler($connection);
case !\is_string($connection):
throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', \get_class($connection)));
throw new \InvalidArgumentException(sprintf('Unsupported Connection: %s.', \get_class($connection)));
case 0 === strpos($connection, 'file://'):
return new StrictSessionHandler(new NativeFileSessionHandler(substr($connection, 7)));
......@@ -80,6 +80,6 @@ class SessionHandlerFactory
return new PdoSessionHandler($connection);
}
throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', $connection));
throw new \InvalidArgumentException(sprintf('Unsupported Connection: %s.', $connection));
}
}
......@@ -148,7 +148,7 @@ class MockArraySessionStorage implements SessionStorageInterface
public function save()
{
if (!$this->started || $this->closed) {
throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.');
throw new \RuntimeException('Trying to save a session that was not started yet or was already closed');
}
// nothing to do since we don't persist the session data
$this->closed = false;
......@@ -186,7 +186,7 @@ class MockArraySessionStorage implements SessionStorageInterface
public function getBag($name)
{
if (!isset($this->bags[$name])) {
throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name));
throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
}
if (!$this->started) {
......
......@@ -37,7 +37,7 @@ class MockFileSessionStorage extends MockArraySessionStorage
}
if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) {
throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $savePath));
throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $savePath));
}
$this->savePath = $savePath;
......@@ -87,7 +87,7 @@ class MockFileSessionStorage extends MockArraySessionStorage
public function save()
{
if (!$this->started) {
throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.');
throw new \RuntimeException('Trying to save a session that was not started yet or was already closed');
}
$data = $this->data;
......
......@@ -17,11 +17,6 @@ use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandle
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
// Help opcache.preload discover always-needed symbols
class_exists(MetadataBag::class);
class_exists(StrictSessionHandler::class);
class_exists(SessionHandlerProxy::class);
/**
* This provides a base class for session attribute storage.
*
......@@ -154,7 +149,7 @@ class NativeSessionStorage implements SessionStorageInterface
// ok to try and start the session
if (!session_start()) {
throw new \RuntimeException('Failed to start the session.');
throw new \RuntimeException('Failed to start the session');
}
if (null !== $this->emulateSameSite) {
......@@ -316,7 +311,7 @@ class NativeSessionStorage implements SessionStorageInterface
public function getBag($name)
{
if (!isset($this->bags[$name])) {
throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name));
throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
}
if (!$this->started && $this->saveHandler->isActive()) {
......
......@@ -88,7 +88,7 @@ abstract class AbstractProxy
public function setId($id)
{
if ($this->isActive()) {
throw new \LogicException('Cannot change the ID of an active session.');
throw new \LogicException('Cannot change the ID of an active session');
}
session_id($id);
......@@ -114,7 +114,7 @@ abstract class AbstractProxy
public function setName($name)
{
if ($this->isActive()) {
throw new \LogicException('Cannot change the name of an active session.');
throw new \LogicException('Cannot change the name of an active session');
}
session_name($name);
......
......@@ -128,14 +128,6 @@ class ResponseHeaderBagTest extends TestCase
$this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; secure', $bag);
}
public function testClearCookieSamesite()
{
$bag = new ResponseHeaderBag([]);
$bag->clearCookie('foo', '/', null, true, false, 'none');
$this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; secure; samesite=none', $bag);
}
public function testReplace()
{
$bag = new ResponseHeaderBag([]);
......
......@@ -92,7 +92,7 @@ final class Address
return new self($address);
}
throw new InvalidArgumentException(sprintf('An address can be an instance of Address or a string ("%s") given).', get_debug_type($address)));
throw new InvalidArgumentException(sprintf('An address can be an instance of Address or a string ("%s") given).', \is_object($address) ? \get_class($address) : \gettype($address)));
}
/**
......
......@@ -24,7 +24,7 @@ abstract class SMime
protected function normalizeFilePath(string $path): string
{
if (!file_exists($path)) {
throw new RuntimeException(sprintf('File does not exist: "%s".', $path));
throw new RuntimeException(sprintf('File does not exist: %s.', $path));
}
return 'file://'.str_replace('\\', '/', realpath($path));
......
......@@ -20,7 +20,9 @@ use Symfony\Component\Mime\Exception\AddressEncoderException;
* SMTP servers.
*
* This encoder does not support email addresses with non-ASCII characters in
* local-part (the substring before @).
* local-part (the substring before @). To send to such addresses, use
* Utf8AddressEncoder together with SmtpUtf8Handler. Your outbound SMTP server must support
* the SMTPUTF8 extension.
*
* @author Christian Schmidt
*/
......
......@@ -150,7 +150,7 @@ final class Headers
$name = strtolower($header->getName());
if (isset($map[$name]) && !$header instanceof $map[$name]) {
throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $map[$name], get_debug_type($header)));
throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $map[$name], \get_class($header)));
}
if (\in_array($name, self::$uniqueHeaders, true) && isset($this->headers[$name]) && \count($this->headers[$name]) > 0) {
......
......@@ -55,13 +55,13 @@ final class MessageConverter
} elseif ($parts[0] instanceof TextPart) {
$email = self::createEmailFromTextPart($message, $parts[0]);
} else {
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
return self::attachParts($email, \array_slice($parts, 1));
}
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
private static function createEmailFromTextPart(Message $message, TextPart $part): Email
......@@ -73,7 +73,7 @@ final class MessageConverter
return (new Email(clone $message->getHeaders()))->html($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8');
}
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
private static function createEmailFromAlternativePart(Message $message, AlternativePart $part): Email
......@@ -90,7 +90,7 @@ final class MessageConverter
;
}
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
private static function createEmailFromRelatedPart(Message $message, RelatedPart $part): Email
......@@ -101,7 +101,7 @@ final class MessageConverter
} elseif ($parts[0] instanceof TextPart) {
$email = self::createEmailFromTextPart($message, $parts[0]);
} else {
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($message)));
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
return self::attachParts($email, \array_slice($parts, 1));
......@@ -111,7 +111,7 @@ final class MessageConverter
{
foreach ($parts as $part) {
if (!$part instanceof DataPart) {
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', get_debug_type($email)));
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($email)));
}
$headers = $part->getPreparedHeaders();
......
......@@ -526,7 +526,6 @@ final class MimeTypes implements MimeTypesInterface
'application/vnd.ms-ims' => ['ims'],
'application/vnd.ms-lrm' => ['lrm'],
'application/vnd.ms-officetheme' => ['thmx'],
'application/vnd.ms-outlook' => ['msg'],
'application/vnd.ms-pki.seccat' => ['cat'],
'application/vnd.ms-pki.stl' => ['stl'],
'application/vnd.ms-powerpoint' => ['ppt', 'pps', 'pot', 'ppz'],
......@@ -2375,7 +2374,6 @@ final class MimeTypes implements MimeTypesInterface
'mseed' => ['application/vnd.fdsn.mseed'],
'mseq' => ['application/vnd.mseq'],
'msf' => ['application/vnd.epson.msf'],
'msg' => ['application/vnd.ms-outlook'],
'msh' => ['model/mesh'],
'msi' => ['application/x-msdownload', 'application/x-msi'],
'msl' => ['application/vnd.mobius.msl'],
......
......@@ -91,7 +91,7 @@ abstract class AbstractMultipartPart extends AbstractPart
private function getBoundary(): string
{
if (null === $this->boundary) {
$this->boundary = strtr(base64_encode(random_bytes(6)), '+/', '-_');
$this->boundary = '_=_symfony_'.time().'_'.bin2hex(random_bytes(16)).'_=_';
}
return $this->boundary;
......
......@@ -57,7 +57,7 @@ class DataPart extends TextPart
}
if (false === $handle = @fopen($path, 'r', false)) {
throw new InvalidArgumentException(sprintf('Unable to open path "%s".', $path));
throw new InvalidArgumentException(sprintf('Unable to open path "%s"', $path));
}
$p = new self($handle, $name ?: basename($path), $contentType);
$p->handle = $handle;
......
......@@ -34,7 +34,7 @@ final class FormDataPart extends AbstractMultipartPart
foreach ($fields as $name => $value) {
if (!\is_string($value) && !\is_array($value) && !$value instanceof TextPart) {
throw new InvalidArgumentException(sprintf('A form field value can only be a string, an array, or an instance of TextPart ("%s" given).', get_debug_type($value)));
throw new InvalidArgumentException(sprintf('A form field value can only be a string, an array, or an instance of TextPart ("%s" given).', \is_object($value) ? \get_class($value) : \gettype($value)));
}
$this->fields[$name] = $value;
......
......@@ -31,7 +31,7 @@ class SMimePart extends AbstractPart
parent::__construct();
if (!\is_string($body) && !is_iterable($body)) {
throw new \TypeError(sprintf('The body of "%s" must be a string or a iterable (got "%s").', self::class, get_debug_type($body)));
throw new \TypeError(sprintf('The body of "%s" must be a string or a iterable (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body)));
}
$this->body = $body;
......
......@@ -40,7 +40,7 @@ class TextPart extends AbstractPart
parent::__construct();
if (!\is_string($body) && !\is_resource($body)) {
throw new \TypeError(sprintf('The body of "%s" must be a string or a resource (got "%s").', self::class, get_debug_type($body)));
throw new \TypeError(sprintf('The body of "%s" must be a string or a resource (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body)));
}
$this->body = $body;
......
......@@ -33,7 +33,7 @@ abstract class SMimeTestCase extends TestCase
protected function normalizeFilePath(string $path): string
{
if (!file_exists($path)) {
throw new RuntimeException(sprintf('File does not exist: "%s"', $path));
throw new RuntimeException(sprintf('File does not exist: %s', $path));
}
return str_replace('\\', '/', realpath($path));
......
......@@ -91,16 +91,4 @@ class FormDataPartTest extends TestCase
$this->assertEquals($foo, $parts[0]->bodyToString());
$this->assertEquals($bar, $parts[1]->bodyToString());
}
public function testBoundaryContentTypeHeader()
{
$f = new FormDataPart([
'file' => new DataPart('data.csv', 'data.csv', 'text/csv'),
]);
$headers = $f->getPreparedHeaders()->toArray();
$this->assertRegExp(
'/^Content-Type: multipart\/form-data; boundary=[a-zA-Z0-9\-_]{8}$/',
$headers[0]
);
}
}
......@@ -18,8 +18,7 @@
"require": {
"php": "^7.2.5",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.15"
"symfony/polyfill-mbstring": "^1.0"
},
"require-dev": {
"egulias/email-validator": "^2.1.10",
......@@ -37,7 +36,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
"dev-master": "5.0-dev"
}
}
}
Symfony Polyfill / Intl: Idn
============================
This component provides [`idn_to_ascii`](https://php.net/idn-to-ascii) and [`idn_to_utf8`](https://php.net/idn-to-utf8) functions to users who run php versions without the [Intl](https://php.net/intl) extension.
This component provides `idn_to_ascii` and `idn_to_utf8` functions to users who run php versions without the intl extension.
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
......
......@@ -11,7 +11,7 @@
use Symfony\Polyfill\Intl\Idn as p;
if (!defined('IDNA_DEFAULT')) {
if (!function_exists('idn_to_ascii')) {
define('U_IDNA_PROHIBITED_ERROR', 66560);
define('U_IDNA_ERROR_START', 66560);
define('U_IDNA_UNASSIGNED_ERROR', 66561);
......@@ -48,9 +48,7 @@ if (!defined('IDNA_DEFAULT')) {
define('IDNA_ERROR_INVALID_ACE_LABEL', 1024);
define('IDNA_ERROR_BIDI', 2048);
define('IDNA_ERROR_CONTEXTJ', 4096);
}
if (!function_exists('idn_to_ascii')) {
if (PHP_VERSION_ID < 70400) {
function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); }
function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); }
......
......@@ -30,7 +30,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-master": "1.14-dev"
}
}
}
......@@ -2,7 +2,7 @@ Symfony Polyfill / Mbstring
===========================
This component provides a partial, native PHP implementation for the
[Mbstring](https://php.net/mbstring) extension.
[Mbstring](http://php.net/mbstring) extension.
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
......
......@@ -11,13 +11,11 @@
use Symfony\Polyfill\Mbstring as p;
if (!defined('MB_CASE_UPPER')) {
if (!function_exists('mb_strlen')) {
define('MB_CASE_UPPER', 0);
define('MB_CASE_LOWER', 1);
define('MB_CASE_TITLE', 2);
}
if (!function_exists('mb_strlen')) {
function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
......
......@@ -28,7 +28,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-master": "1.14-dev"
}
}
}
......@@ -16,7 +16,7 @@ Moved to core since 7.2 (was in the optional XML extension earlier):
- [`utf8_decode`](https://php.net/utf8_decode)
Also, it provides a constant added to PHP 7.2:
- [`PHP_OS_FAMILY`](https://php.net/reserved.constants#constant.php-os-family)
- [`PHP_OS_FAMILY`](http://php.net/manual/en/reserved.constants.php#constant.php-os-family)
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
......
......@@ -25,7 +25,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-master": "1.14-dev"
}
}
}
polyfill-php80 @ 8854dc88
Subproject commit 8854dc880784d2ae32908b75824754339b5c0555
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment