diff --git a/composer.lock b/composer.lock old mode 100755 new mode 100644 index b31d65cfe..24317824b --- a/composer.lock +++ b/composer.lock @@ -18,7 +18,13 @@ "type": "zip", "url": "https://api.github.com/repos/adbario/php-dot-notation/zipball/081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae", "reference": "081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", @@ -71,7 +77,13 @@ "type": "zip", "url": "https://api.github.com/repos/aliyun/openapi-sdk-php-client/zipball/5bc6f6d660797dcee2c3aef29700ab41ee764f4d", "reference": "5bc6f6d660797dcee2c3aef29700ab41ee764f4d", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "adbario/php-dot-notation": "^2.4.1", @@ -155,7 +167,13 @@ "type": "zip", "url": "https://api.github.com/repos/aliyun/aliyun-oss-php-sdk/zipball/572d0f8e099e8630ae7139ed3fdedb926c7a760f", "reference": "572d0f8e099e8630ae7139ed3fdedb926c7a760f", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=5.3" @@ -200,7 +218,13 @@ "type": "zip", "url": "https://api.github.com/repos/clagiordano/weblibs-configmanager/zipball/8802c7396d61a923c9a73e37ead062b24bb1b273", "reference": "8802c7396d61a923c9a73e37ead062b24bb1b273", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", @@ -245,17 +269,23 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.3.2", + "version": "v3.3.1", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8" + "reference": "be85b3f05b46c39bbc0d95f6c071ddff669510fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8", - "shasum": "" + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/be85b3f05b46c39bbc0d95f6c071ddff669510fa", + "reference": "be85b3f05b46c39bbc0d95f6c071ddff669510fa", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.2|^8.0", @@ -294,7 +324,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.1" }, "funding": [ { @@ -302,7 +332,7 @@ "type": "github" } ], - "time": "2022-09-10T18:51:20+00:00" + "time": "2022-01-18T15:43:28+00:00" }, { "name": "ebaoquan/junziqian_sdk", @@ -347,7 +377,13 @@ "type": "zip", "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/523407fb06eb9e5f3d59889b3978d5bfe94299c8", "reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0" @@ -408,7 +444,13 @@ "type": "zip", "url": "https://api.github.com/repos/guzzle/command/zipball/3372bcfd79d4b357b6871665bf06155515e8d844", "reference": "3372bcfd79d4b357b6871665bf06155515e8d844", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "guzzlehttp/guzzle": "^7.5.1", @@ -491,7 +533,13 @@ "type": "zip", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", @@ -617,7 +665,13 @@ "type": "zip", "url": "https://api.github.com/repos/guzzle/guzzle-services/zipball/f4bb1c205152a56741624b88753732e01a60565c", "reference": "f4bb1c205152a56741624b88753732e01a60565c", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "guzzlehttp/command": "^1.3", @@ -694,33 +748,35 @@ }, { "name": "guzzlehttp/promises", - "version": "2.0.0", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6" + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", - "shasum": "" + "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": "^7.2.5 || ^8.0" + "php": ">=5.5" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "symfony/phpunit-bridge": "^4.4 || ^5.1" }, "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -757,7 +813,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.0" + "source": "https://github.com/guzzle/promises/tree/1.5.3" }, "funding": [ { @@ -773,7 +829,7 @@ "type": "tidelift" } ], - "time": "2023-05-21T13:50:22+00:00" + "time": "2023-05-21T12:31:43+00:00" }, { "name": "guzzlehttp/psr7", @@ -787,7 +843,13 @@ "type": "zip", "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", "reference": "b635f279edd83fc275f822a1188157ffea568ff6", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.2.5 || ^8.0", @@ -903,7 +965,13 @@ "type": "zip", "url": "https://api.github.com/repos/guzzle/uri-template/zipball/b945d74a55a25a949158444f09ec0d3c120d69e2", "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.2.5 || ^8.0", @@ -977,36 +1045,39 @@ }, { "name": "maennchen/zipstream-php", - "version": "3.1.0", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1" + "reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b8174494eda667f7d13876b4a7bfef0f62a7c0d1", - "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1", - "shasum": "" + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3", + "reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-mbstring": "*", - "ext-zlib": "*", - "php-64bit": "^8.1" + "myclabs/php-enum": "^1.5", + "php": "^8.0", + "psr/http-message": "^1.0" }, "require-dev": { "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.16", - "guzzlehttp/guzzle": "^7.5", + "friendsofphp/php-cs-fixer": "^3.9", + "guzzlehttp/guzzle": "^6.5.3 || ^7.2.0", "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.5", - "phpunit/phpunit": "^10.0", + "php-coveralls/php-coveralls": "^2.4", + "phpunit/phpunit": "^8.5.8 || ^9.4.2", "vimeo/psalm": "^5.0" }, - "suggest": { - "guzzlehttp/psr7": "^2.4", - "psr/http-message": "^2.0" - }, "type": "library", "autoload": { "psr-4": { @@ -1042,7 +1113,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.0" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/2.4.0" }, "funding": [ { @@ -1054,7 +1125,7 @@ "type": "open_collective" } ], - "time": "2023-06-21T14:59:35+00:00" + "time": "2022-12-08T12:29:14+00:00" }, { "name": "markbaker/complex", @@ -1068,7 +1139,13 @@ "type": "zip", "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9", "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.2 || ^8.0" @@ -1119,7 +1196,13 @@ "type": "zip", "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c", "reference": "728434227fe21be27ff6d86621a1b13107a2562c", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.1 || ^8.0" @@ -1175,7 +1258,13 @@ "type": "zip", "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1", "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.2", @@ -1277,7 +1366,13 @@ "type": "zip", "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/9b87907a81b87bc76d19a7fb2d61e61486ee9edb", "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^5.4 || ^7.0 || ^8.0", @@ -1326,6 +1421,72 @@ }, "time": "2021-06-14T00:11:39+00:00" }, + { + "name": "myclabs/php-enum", + "version": "1.8.3", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "b942d263c641ddb5190929ff840c68f78713e937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/b942d263c641ddb5190929ff840c68f78713e937", + "reference": "b942d263c641ddb5190929ff840c68f78713e937", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/1.8.3" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", + "type": "tidelift" + } + ], + "time": "2021-07-05T08:18:36+00:00" + }, { "name": "nyholm/psr7", "version": "1.8.0", @@ -1338,7 +1499,13 @@ "type": "zip", "url": "https://api.github.com/repos/Nyholm/psr7/zipball/3cb4d163b58589e47b35103e8e5e6a6a475b47be", "reference": "3cb4d163b58589e47b35103e8e5e6a6a475b47be", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.2", @@ -1416,7 +1583,13 @@ "type": "zip", "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/b846a689844cef114e8079d8c80f0afd96745ae3", "reference": "b846a689844cef114e8079d8c80f0afd96745ae3", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.1 || ^8.0", @@ -1482,7 +1655,13 @@ "type": "zip", "url": "https://api.github.com/repos/overtrue/socialite/zipball/e55fdf50f8003be8f03a85a7e5a5b7c5716f4c9a", "reference": "e55fdf50f8003be8f03a85a7e5a5b7c5716f4c9a", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", @@ -1545,17 +1724,23 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.29.0", + "version": "1.28.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0" + "reference": "6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/fde2ccf55eaef7e86021ff1acce26479160a0fa0", - "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0", - "shasum": "" + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a", + "reference": "6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-ctype": "*", @@ -1572,7 +1757,7 @@ "ext-zip": "*", "ext-zlib": "*", "ezyang/htmlpurifier": "^4.15", - "maennchen/zipstream-php": "^2.1 || ^3.0", + "maennchen/zipstream-php": "^2.1", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", "php": "^7.4 || ^8.0", @@ -1584,12 +1769,12 @@ "dealerdirect/phpcodesniffer-composer-installer": "dev-main", "dompdf/dompdf": "^1.0 || ^2.0", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.3", + "mitoteam/jpgraph": "^10.2.4", "mpdf/mpdf": "^8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0 || ^10.0", + "phpunit/phpunit": "^8.5 || ^9.0", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, @@ -1644,9 +1829,9 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.0" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.28.0" }, - "time": "2023-06-14T22:48:31+00:00" + "time": "2023-02-25T12:24:49+00:00" }, { "name": "psr/cache", @@ -1660,7 +1845,13 @@ "type": "zip", "url": "https://api.github.com/repos/php-fig/cache/zipball/213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=8.0.0" @@ -1709,7 +1900,13 @@ "type": "zip", "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.4.0" @@ -1747,21 +1944,27 @@ }, { "name": "psr/http-client", - "version": "1.0.2", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "shasum": "" + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" + "psr/http-message": "^1.0" }, "type": "library", "extra": { @@ -1781,7 +1984,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", @@ -1793,9 +1996,9 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/1.0.2" + "source": "https://github.com/php-fig/http-client/tree/master" }, - "time": "2023-04-10T20:12:12+00:00" + "time": "2020-06-29T06:28:15+00:00" }, { "name": "psr/http-factory", @@ -1809,7 +2012,13 @@ "type": "zip", "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", "reference": "e616d01114759c4c489f93b099585439f795fe35", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.0.0", @@ -1864,7 +2073,13 @@ "type": "zip", "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.2 || ^8.0" @@ -1917,7 +2132,13 @@ "type": "zip", "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=5.3.0" @@ -1967,7 +2188,13 @@ "type": "zip", "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=5.3.0" @@ -2018,7 +2245,13 @@ "type": "zip", "url": "https://api.github.com/repos/tencentyun/cos-php-sdk-v5/zipball/06ccc95599635abd3f431f470b79b8fb8ddbd6a0", "reference": "06ccc95599635abd3f431f470b79b8fb8ddbd6a0", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-curl": "*", @@ -2086,7 +2319,13 @@ "type": "zip", "url": "https://api.github.com/repos/qiniu/php-sdk/zipball/1c6bc89166e524a40ee42bf516fb99ffc6401c82", "reference": "1c6bc89166e524a40ee42bf516fb99ffc6401c82", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=5.3.3" @@ -2141,7 +2380,13 @@ "type": "zip", "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", "reference": "120b605dfeb996808c31b6477290a714d356e822", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=5.6" @@ -2175,17 +2420,23 @@ }, { "name": "rmccue/requests", - "version": "v2.0.7", + "version": "v2.0.5", "source": { "type": "git", "url": "https://github.com/WordPress/Requests.git", - "reference": "e14a6f4e7438d3f8da3f2657759e6367b906ee23" + "reference": "b717f1d2f4ef7992ec0c127747ed8b7e170c2f49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/Requests/zipball/e14a6f4e7438d3f8da3f2657759e6367b906ee23", - "reference": "e14a6f4e7438d3f8da3f2657759e6367b906ee23", - "shasum": "" + "url": "https://api.github.com/repos/WordPress/Requests/zipball/b717f1d2f4ef7992ec0c127747ed8b7e170c2f49", + "reference": "b717f1d2f4ef7992ec0c127747ed8b7e170c2f49", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", @@ -2252,7 +2503,7 @@ "issues": "https://github.com/WordPress/Requests/issues", "source": "https://github.com/WordPress/Requests" }, - "time": "2023-06-02T07:35:42+00:00" + "time": "2022-10-11T08:15:28+00:00" }, { "name": "symfony/cache", @@ -2266,7 +2517,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/cache/zipball/e2013521c0f07473ae69a01fce0af78fc3ec0f23", "reference": "e2013521c0f07473ae69a01fce0af78fc3ec0f23", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.2.5", @@ -2363,7 +2620,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.2.5", @@ -2432,25 +2695,31 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", - "shasum": "" + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1" + "php": ">=8.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -2479,7 +2748,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" }, "funding": [ { @@ -2495,26 +2764,31 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { "name": "symfony/http-client", - "version": "v6.2.12", + "version": "v6.0.20", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "7ef37b91629937843e8f52a2da5587ff16d75d25" + "reference": "541c04560da1875f62c963c3aab6ea12a7314e11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/7ef37b91629937843e8f52a2da5587ff16d75d25", - "reference": "7ef37b91629937843e8f52a2da5587ff16d75d25", - "shasum": "" + "url": "https://api.github.com/repos/symfony/http-client/zipball/541c04560da1875f62c963c3aab6ea12a7314e11", + "reference": "541c04560da1875f62c963c3aab6ea12a7314e11", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1", + "php": ">=8.0.2", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.1|^3", "symfony/http-client-contracts": "^3", "symfony/service-contracts": "^1.0|^2|^3" }, @@ -2532,7 +2806,6 @@ "guzzlehttp/promises": "^1.4", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", - "php-http/message-factory": "^1.0", "psr/http-client": "^1.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", @@ -2564,11 +2837,8 @@ ], "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", - "keywords": [ - "http" - ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.2.12" + "source": "https://github.com/symfony/http-client/tree/v6.0.20" }, "funding": [ { @@ -2584,29 +2854,38 @@ "type": "tidelift" } ], - "time": "2023-06-24T11:48:11+00:00" + "time": "2023-01-30T15:41:07+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.3.0", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "3b66325d0176b4ec826bffab57c9037d759c31fb" + "reference": "4184b9b63af1edaf35b6a7974c6f1f9f33294129" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/3b66325d0176b4ec826bffab57c9037d759c31fb", - "reference": "3b66325d0176b4ec826bffab57c9037d759c31fb", - "shasum": "" + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/4184b9b63af1edaf35b6a7974c6f1f9f33294129", + "reference": "4184b9b63af1edaf35b6a7974c6f1f9f33294129", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1" + "php": ">=8.0.2" + }, + "suggest": { + "symfony/http-client-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -2616,10 +2895,7 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2646,7 +2922,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.0.2" }, "funding": [ { @@ -2662,24 +2938,30 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2022-04-12T16:11:42+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.1.12", + "version": "v6.0.20", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "bd1bcfb0eba14de22c4d086c5023e608f37366ed" + "reference": "e16b2676a4b3b1fa12378a20b29c364feda2a8d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/bd1bcfb0eba14de22c4d086c5023e608f37366ed", - "reference": "bd1bcfb0eba14de22c4d086c5023e608f37366ed", - "shasum": "" + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e16b2676a4b3b1fa12378a20b29c364feda2a8d6", + "reference": "e16b2676a4b3b1fa12378a20b29c364feda2a8d6", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1", + "php": ">=8.0.2", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.1" }, @@ -2721,7 +3003,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.1.12" + "source": "https://github.com/symfony/http-foundation/tree/v6.0.20" }, "funding": [ { @@ -2737,24 +3019,30 @@ "type": "tidelift" } ], - "time": "2023-01-30T15:43:30+00:00" + "time": "2023-01-30T15:41:07+00:00" }, { "name": "symfony/mime", - "version": "v6.3.0", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad" + "reference": "d7052547a0070cbeadd474e172b527a00d657301" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/7b5d2121858cd6efbed778abce9cfdd7ab1f62ad", - "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad", - "shasum": "" + "url": "https://api.github.com/repos/symfony/mime/zipball/d7052547a0070cbeadd474e172b527a00d657301", + "reference": "d7052547a0070cbeadd474e172b527a00d657301", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1", + "php": ">=8.0.2", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -2763,16 +3051,15 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<5.4", - "symfony/serializer": "<6.2" + "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", - "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/property-access": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "^6.2" + "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" }, "type": "library", "autoload": { @@ -2804,7 +3091,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.3.0" + "source": "https://github.com/symfony/mime/tree/v6.0.19" }, "funding": [ { @@ -2820,7 +3107,7 @@ "type": "tidelift" } ], - "time": "2023-04-28T15:57:00+00:00" + "time": "2023-01-11T11:50:03+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2834,7 +3121,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1" @@ -2916,7 +3209,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da", "reference": "639084e360537a19f9ee352433b84ce831f3d2da", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1", @@ -3003,7 +3302,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1" @@ -3087,7 +3392,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1" @@ -3170,7 +3481,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1" @@ -3246,7 +3563,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1" @@ -3325,7 +3648,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1" @@ -3408,7 +3737,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1" @@ -3487,7 +3822,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/28a732c05bbad801304ad5a5c674cf2970508993", "reference": "28a732c05bbad801304ad5a5c674cf2970508993", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.2.5", @@ -3575,7 +3916,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.2.5", @@ -3648,20 +3995,26 @@ }, { "name": "symfony/var-exporter", - "version": "v6.3.0", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "db5416d04269f2827d8c54331ba4cfa42620d350" + "reference": "df56f53818c2d5d9f683f4ad2e365ba73a3b69d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/db5416d04269f2827d8c54331ba4cfa42620d350", - "reference": "db5416d04269f2827d8c54331ba4cfa42620d350", - "shasum": "" + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df56f53818c2d5d9f683f4ad2e365ba73a3b69d2", + "reference": "df56f53818c2d5d9f683f4ad2e365ba73a3b69d2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1" + "php": ">=8.0.2" }, "require-dev": { "symfony/var-dumper": "^5.4|^6.0" @@ -3697,12 +4050,10 @@ "export", "hydrate", "instantiate", - "lazy-loading", - "proxy", "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.3.0" + "source": "https://github.com/symfony/var-exporter/tree/v6.0.19" }, "funding": [ { @@ -3718,7 +4069,7 @@ "type": "tidelift" } ], - "time": "2023-04-21T08:48:44+00:00" + "time": "2023-01-13T08:34:10+00:00" }, { "name": "symfony/yaml", @@ -3732,7 +4083,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/yaml/zipball/02c1859112aa779d9ab394ae4f3381911d84052b", "reference": "02c1859112aa779d9ab394ae4f3381911d84052b", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=5.3.9", @@ -3785,7 +4142,13 @@ "type": "zip", "url": "https://api.github.com/repos/TencentCloud/tencentcloud-sdk-php/zipball/4aea86d788df2ed8e1ffafbfc7703f7263b84cde", "reference": "4aea86d788df2ed8e1ffafbfc7703f7263b84cde", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "guzzlehttp/guzzle": "^6.3 || ^7.0", @@ -3835,7 +4198,13 @@ "type": "zip", "url": "https://api.github.com/repos/TheNorthMemory/xml/zipball/6f50c63450a0b098772423f8bdc3c4ad2c4c30bb", "reference": "6f50c63450a0b098772423f8bdc3c4ad2c4c30bb", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-libxml": "*", @@ -3886,7 +4255,13 @@ "type": "zip", "url": "https://api.github.com/repos/top-think/framework/zipball/66eb9cf4d627df12911344cd328faf9bb596bf2c", "reference": "66eb9cf4d627df12911344cd328faf9bb596bf2c", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", @@ -3951,7 +4326,13 @@ "type": "zip", "url": "https://api.github.com/repos/top-think/think-helper/zipball/769acbe50a4274327162f9c68ec2e89a38eb2aff", "reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1.0" @@ -3997,7 +4378,13 @@ "type": "zip", "url": "https://api.github.com/repos/top-think/think-multi-app/zipball/4055a6187296ac16c0bc7bbab4ed5d92f82f791c", "reference": "4055a6187296ac16c0bc7bbab4ed5d92f82f791c", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1.0", @@ -4045,7 +4432,13 @@ "type": "zip", "url": "https://api.github.com/repos/top-think/think-orm/zipball/10528ebf4a5106b19c3bac9c6deae7a67ff49de6", "reference": "10528ebf4a5106b19c3bac9c6deae7a67ff49de6", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", @@ -4100,7 +4493,13 @@ "type": "zip", "url": "https://api.github.com/repos/top-think/think-template/zipball/6d25642ae0e306166742fd7073dc7a159e18073c", "reference": "6d25642ae0e306166742fd7073dc7a159e18073c", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1.0", @@ -4141,7 +4540,13 @@ "type": "zip", "url": "https://api.github.com/repos/top-think/think-view/zipball/edce0ae2c9551ab65f9e94a222604b0dead3576d", "reference": "edce0ae2c9551ab65f9e94a222604b0dead3576d", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1.0", @@ -4172,17 +4577,23 @@ }, { "name": "w7corp/easywechat", - "version": "6.12.3", + "version": "6.8.0", "source": { "type": "git", "url": "https://github.com/w7corp/easywechat.git", - "reference": "10b9f31b61b4e5327c9e4457dffcf307de2deb6c" + "reference": "60f0b4ba2ac3144df1a2291193daa34beb949d26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/w7corp/easywechat/zipball/10b9f31b61b4e5327c9e4457dffcf307de2deb6c", - "reference": "10b9f31b61b4e5327c9e4457dffcf307de2deb6c", - "shasum": "" + "url": "https://api.github.com/repos/w7corp/easywechat/zipball/60f0b4ba2ac3144df1a2291193daa34beb949d26", + "reference": "60f0b4ba2ac3144df1a2291193daa34beb949d26", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-curl": "*", @@ -4191,10 +4602,10 @@ "ext-openssl": "*", "ext-simplexml": "*", "ext-sodium": "*", - "monolog/monolog": "^2.2|^3.0", + "monolog/monolog": "^2.2", "nyholm/psr7": "^1.5", "nyholm/psr7-server": "^1.0", - "overtrue/socialite": "^3.5.4|^4.0.1", + "overtrue/socialite": "^3.5|^4.0.1", "php": ">=8.0.2", "psr/http-client": "^1.0", "psr/simple-cache": "^1.0|^2.0|^3.0", @@ -4260,7 +4671,7 @@ ], "support": { "issues": "https://github.com/w7corp/easywechat/issues", - "source": "https://github.com/w7corp/easywechat/tree/6.12.3" + "source": "https://github.com/w7corp/easywechat/tree/6.8.0" }, "funding": [ { @@ -4268,7 +4679,7 @@ "type": "github" } ], - "time": "2023-07-05T14:14:28+00:00" + "time": "2022-09-25T13:05:18+00:00" }, { "name": "webmozart/assert", @@ -4282,7 +4693,13 @@ "type": "zip", "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-ctype": "*", @@ -4342,7 +4759,13 @@ "type": "zip", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1069c7a3fca74578022fab6f81643248d02f8e63", "reference": "1069c7a3fca74578022fab6f81643248d02f8e63", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1.3", @@ -4431,7 +4854,13 @@ "type": "zip", "url": "https://api.github.com/repos/top-think/think-trace/zipball/136cd5d97e8bdb780e4b5c1637c588ed7ca3e142", "reference": "136cd5d97e8bdb780e4b5c1637c588ed7ca3e142", - "shasum": "" + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": ">=7.1.0", diff --git a/composer.phar:Zone.Identifier b/composer.phar:Zone.Identifier deleted file mode 100755 index 2130d17f8..000000000 --- a/composer.phar:Zone.Identifier +++ /dev/null @@ -1,4 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=https://getcomposer.org/download/ -HostUrl=https://getcomposer.org/download/2.5.8/composer.phar diff --git a/public/MP_verify_jJCfJRvjXskoiDaS.txt b/public/MP_verify_jJCfJRvjXskoiDaS.txt new file mode 100755 index 000000000..6de07aa0a --- /dev/null +++ b/public/MP_verify_jJCfJRvjXskoiDaS.txt @@ -0,0 +1 @@ +jJCfJRvjXskoiDaS \ No newline at end of file diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index cdf6ba48a..6588f3b8c 100755 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -8,6 +8,7 @@ $baseDir = dirname($vendorDir); return array( '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', + 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', '9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php', diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 070ac1ba0..2118e273e 100755 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -9,7 +9,7 @@ return array( 'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'), 'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'), 'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'), - 'think\\' => array($vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/framework/src/think'), + 'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src'), 'com\\junziqian\\sdk\\' => array($vendorDir . '/ebaoquan/junziqian_sdk/src/com/junziqian/sdk'), 'clagiordano\\weblibs\\configmanager\\' => array($vendorDir . '/clagiordano/weblibs-configmanager/src'), 'app\\' => array($baseDir . '/app'), @@ -50,6 +50,7 @@ return array( 'OSS\\' => array($vendorDir . '/aliyuncs/oss-sdk-php/src/OSS'), 'Nyholm\\Psr7\\' => array($vendorDir . '/nyholm/psr7/src'), 'Nyholm\\Psr7Server\\' => array($vendorDir . '/nyholm/psr7-server/src'), + 'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'), 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'), 'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'), 'JmesPath\\' => array($vendorDir . '/mtdowling/jmespath.php/src'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index c997d35fb..210bafb1c 100755 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -9,6 +9,7 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e public static $files = array ( '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', + 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php', @@ -113,6 +114,7 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e ), 'M' => array ( + 'MyCLabs\\Enum\\' => 13, 'Monolog\\' => 8, 'Matrix\\' => 7, ), @@ -160,10 +162,10 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e ), 'think\\' => array ( - 0 => __DIR__ . '/..' . '/topthink/think-helper/src', - 1 => __DIR__ . '/..' . '/topthink/think-orm/src', - 2 => __DIR__ . '/..' . '/topthink/think-template/src', - 3 => __DIR__ . '/..' . '/topthink/framework/src/think', + 0 => __DIR__ . '/..' . '/topthink/framework/src/think', + 1 => __DIR__ . '/..' . '/topthink/think-helper/src', + 2 => __DIR__ . '/..' . '/topthink/think-orm/src', + 3 => __DIR__ . '/..' . '/topthink/think-template/src', ), 'com\\junziqian\\sdk\\' => array ( @@ -326,6 +328,10 @@ class ComposerStaticInitd2a74ba94e266cc4f45a64c54a292d7e array ( 0 => __DIR__ . '/..' . '/nyholm/psr7-server/src', ), + 'MyCLabs\\Enum\\' => + array ( + 0 => __DIR__ . '/..' . '/myclabs/php-enum/src', + ), 'Monolog\\' => array ( 0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index a0bc98ab4..f0fe042c1 100755 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -275,18 +275,24 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.3.2", - "version_normalized": "3.3.2.0", + "version": "v3.3.1", + "version_normalized": "3.3.1.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8" + "reference": "be85b3f05b46c39bbc0d95f6c071ddff669510fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8", - "shasum": "" + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/be85b3f05b46c39bbc0d95f6c071ddff669510fa", + "reference": "be85b3f05b46c39bbc0d95f6c071ddff669510fa", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.2|^8.0", @@ -301,7 +307,7 @@ "phpstan/phpstan-webmozart-assert": "^1.0", "phpunit/phpunit": "^7.0|^8.0|^9.0" }, - "time": "2022-09-10T18:51:20+00:00", + "time": "2022-01-18T15:43:28+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -327,7 +333,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.1" }, "funding": [ { @@ -748,36 +754,38 @@ }, { "name": "guzzlehttp/promises", - "version": "2.0.0", - "version_normalized": "2.0.0.0", + "version": "1.5.3", + "version_normalized": "1.5.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6" + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", - "shasum": "" + "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": "^7.2.5 || ^8.0" + "php": ">=5.5" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "symfony/phpunit-bridge": "^4.4 || ^5.1" }, - "time": "2023-05-21T13:50:22+00:00", + "time": "2023-05-21T12:31:43+00:00", "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, "installation-source": "dist", "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -814,7 +822,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.0" + "source": "https://github.com/guzzle/promises/tree/1.5.3" }, "funding": [ { @@ -1052,38 +1060,41 @@ }, { "name": "maennchen/zipstream-php", - "version": "3.1.0", - "version_normalized": "3.1.0.0", + "version": "2.4.0", + "version_normalized": "2.4.0.0", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1" + "reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b8174494eda667f7d13876b4a7bfef0f62a7c0d1", - "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1", - "shasum": "" + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3", + "reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-mbstring": "*", - "ext-zlib": "*", - "php-64bit": "^8.1" + "myclabs/php-enum": "^1.5", + "php": "^8.0", + "psr/http-message": "^1.0" }, "require-dev": { "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.16", - "guzzlehttp/guzzle": "^7.5", + "friendsofphp/php-cs-fixer": "^3.9", + "guzzlehttp/guzzle": "^6.5.3 || ^7.2.0", "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.5", - "phpunit/phpunit": "^10.0", + "php-coveralls/php-coveralls": "^2.4", + "phpunit/phpunit": "^8.5.8 || ^9.4.2", "vimeo/psalm": "^5.0" }, - "suggest": { - "guzzlehttp/psr7": "^2.4", - "psr/http-message": "^2.0" - }, - "time": "2023-06-21T14:59:35+00:00", + "time": "2022-12-08T12:29:14+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1120,7 +1131,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.0" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/2.4.0" }, "funding": [ { @@ -1434,6 +1445,75 @@ }, "install-path": "../mtdowling/jmespath.php" }, + { + "name": "myclabs/php-enum", + "version": "1.8.3", + "version_normalized": "1.8.3.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "b942d263c641ddb5190929ff840c68f78713e937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/b942d263c641ddb5190929ff840c68f78713e937", + "reference": "b942d263c641ddb5190929ff840c68f78713e937", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.6.2" + }, + "time": "2021-07-05T08:18:36+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/1.8.3" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", + "type": "tidelift" + } + ], + "install-path": "../myclabs/php-enum" + }, { "name": "nyholm/psr7", "version": "1.8.0", @@ -1680,18 +1760,24 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.29.0", - "version_normalized": "1.29.0.0", + "version": "1.28.0", + "version_normalized": "1.28.0.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0" + "reference": "6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/fde2ccf55eaef7e86021ff1acce26479160a0fa0", - "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0", - "shasum": "" + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a", + "reference": "6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-ctype": "*", @@ -1708,7 +1794,7 @@ "ext-zip": "*", "ext-zlib": "*", "ezyang/htmlpurifier": "^4.15", - "maennchen/zipstream-php": "^2.1 || ^3.0", + "maennchen/zipstream-php": "^2.1", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", "php": "^7.4 || ^8.0", @@ -1720,12 +1806,12 @@ "dealerdirect/phpcodesniffer-composer-installer": "dev-main", "dompdf/dompdf": "^1.0 || ^2.0", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.3", + "mitoteam/jpgraph": "^10.2.4", "mpdf/mpdf": "^8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0 || ^10.0", + "phpunit/phpunit": "^8.5 || ^9.0", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, @@ -1736,7 +1822,7 @@ "mpdf/mpdf": "Option for rendering PDF with PDF Writer", "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" }, - "time": "2023-06-14T22:48:31+00:00", + "time": "2023-02-25T12:24:49+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1782,7 +1868,7 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.0" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.28.0" }, "install-path": "../phpoffice/phpspreadsheet" }, @@ -1903,24 +1989,30 @@ }, { "name": "psr/http-client", - "version": "1.0.2", - "version_normalized": "1.0.2.0", + "version": "1.0.1", + "version_normalized": "1.0.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "shasum": "" + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" + "psr/http-message": "^1.0" }, - "time": "2023-04-10T20:12:12+00:00", + "time": "2020-06-29T06:28:15+00:00", "type": "library", "extra": { "branch-alias": { @@ -1940,7 +2032,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", @@ -1952,7 +2044,7 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/1.0.2" + "source": "https://github.com/php-fig/http-client/tree/master" }, "install-path": "../psr/http-client" }, @@ -2391,18 +2483,24 @@ }, { "name": "rmccue/requests", - "version": "v2.0.7", - "version_normalized": "2.0.7.0", + "version": "v2.0.5", + "version_normalized": "2.0.5.0", "source": { "type": "git", "url": "https://github.com/WordPress/Requests.git", - "reference": "e14a6f4e7438d3f8da3f2657759e6367b906ee23" + "reference": "b717f1d2f4ef7992ec0c127747ed8b7e170c2f49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/Requests/zipball/e14a6f4e7438d3f8da3f2657759e6367b906ee23", - "reference": "e14a6f4e7438d3f8da3f2657759e6367b906ee23", - "shasum": "" + "url": "https://api.github.com/repos/WordPress/Requests/zipball/b717f1d2f4ef7992ec0c127747ed8b7e170c2f49", + "reference": "b717f1d2f4ef7992ec0c127747ed8b7e170c2f49", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-json": "*", @@ -2419,7 +2517,7 @@ "wp-coding-standards/wpcs": "^2.0", "yoast/phpunit-polyfills": "^1.0.0" }, - "time": "2023-06-02T07:35:42+00:00", + "time": "2022-10-11T08:15:28+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2663,27 +2761,33 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", - "version_normalized": "3.3.0.0", + "version": "v3.0.2", + "version_normalized": "3.0.2.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", - "shasum": "" + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1" + "php": ">=8.0.2" }, - "time": "2023-05-23T14:45:45+00:00", + "time": "2022-01-02T09:55:41+00:00", "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -2713,7 +2817,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" }, "funding": [ { @@ -2733,23 +2837,28 @@ }, { "name": "symfony/http-client", - "version": "v6.2.12", - "version_normalized": "6.2.12.0", + "version": "v6.0.20", + "version_normalized": "6.0.20.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "7ef37b91629937843e8f52a2da5587ff16d75d25" + "reference": "541c04560da1875f62c963c3aab6ea12a7314e11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/7ef37b91629937843e8f52a2da5587ff16d75d25", - "reference": "7ef37b91629937843e8f52a2da5587ff16d75d25", - "shasum": "" + "url": "https://api.github.com/repos/symfony/http-client/zipball/541c04560da1875f62c963c3aab6ea12a7314e11", + "reference": "541c04560da1875f62c963c3aab6ea12a7314e11", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1", + "php": ">=8.0.2", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.1|^3", "symfony/http-client-contracts": "^3", "symfony/service-contracts": "^1.0|^2|^3" }, @@ -2767,14 +2876,13 @@ "guzzlehttp/promises": "^1.4", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", - "php-http/message-factory": "^1.0", "psr/http-client": "^1.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/process": "^5.4|^6.0", "symfony/stopwatch": "^5.4|^6.0" }, - "time": "2023-06-24T11:48:11+00:00", + "time": "2023-01-30T15:41:07+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2801,11 +2909,8 @@ ], "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", - "keywords": [ - "http" - ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.2.12" + "source": "https://github.com/symfony/http-client/tree/v6.0.20" }, "funding": [ { @@ -2825,27 +2930,36 @@ }, { "name": "symfony/http-client-contracts", - "version": "v3.3.0", - "version_normalized": "3.3.0.0", + "version": "v3.0.2", + "version_normalized": "3.0.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "3b66325d0176b4ec826bffab57c9037d759c31fb" + "reference": "4184b9b63af1edaf35b6a7974c6f1f9f33294129" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/3b66325d0176b4ec826bffab57c9037d759c31fb", - "reference": "3b66325d0176b4ec826bffab57c9037d759c31fb", - "shasum": "" + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/4184b9b63af1edaf35b6a7974c6f1f9f33294129", + "reference": "4184b9b63af1edaf35b6a7974c6f1f9f33294129", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1" + "php": ">=8.0.2" }, - "time": "2023-05-23T14:45:45+00:00", + "suggest": { + "symfony/http-client-implementation": "" + }, + "time": "2022-04-12T16:11:42+00:00", "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", @@ -2856,10 +2970,7 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2886,7 +2997,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.0.2" }, "funding": [ { @@ -2906,21 +3017,27 @@ }, { "name": "symfony/http-foundation", - "version": "v6.1.12", - "version_normalized": "6.1.12.0", + "version": "v6.0.20", + "version_normalized": "6.0.20.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "bd1bcfb0eba14de22c4d086c5023e608f37366ed" + "reference": "e16b2676a4b3b1fa12378a20b29c364feda2a8d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/bd1bcfb0eba14de22c4d086c5023e608f37366ed", - "reference": "bd1bcfb0eba14de22c4d086c5023e608f37366ed", - "shasum": "" + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e16b2676a4b3b1fa12378a20b29c364feda2a8d6", + "reference": "e16b2676a4b3b1fa12378a20b29c364feda2a8d6", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1", + "php": ">=8.0.2", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.1" }, @@ -2936,7 +3053,7 @@ "suggest": { "symfony/mime": "To use the file extension guesser" }, - "time": "2023-01-30T15:43:30+00:00", + "time": "2023-01-30T15:41:07+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2964,7 +3081,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.1.12" + "source": "https://github.com/symfony/http-foundation/tree/v6.0.20" }, "funding": [ { @@ -2984,21 +3101,27 @@ }, { "name": "symfony/mime", - "version": "v6.3.0", - "version_normalized": "6.3.0.0", + "version": "v6.0.19", + "version_normalized": "6.0.19.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad" + "reference": "d7052547a0070cbeadd474e172b527a00d657301" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/7b5d2121858cd6efbed778abce9cfdd7ab1f62ad", - "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad", - "shasum": "" + "url": "https://api.github.com/repos/symfony/mime/zipball/d7052547a0070cbeadd474e172b527a00d657301", + "reference": "d7052547a0070cbeadd474e172b527a00d657301", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1", + "php": ">=8.0.2", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -3007,18 +3130,17 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<5.4", - "symfony/serializer": "<6.2" + "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", - "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/property-access": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "^6.2" + "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" }, - "time": "2023-04-28T15:57:00+00:00", + "time": "2023-01-11T11:50:03+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3050,7 +3172,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.3.0" + "source": "https://github.com/symfony/mime/tree/v6.0.19" }, "funding": [ { @@ -4082,26 +4204,32 @@ }, { "name": "symfony/var-exporter", - "version": "v6.3.0", - "version_normalized": "6.3.0.0", + "version": "v6.0.19", + "version_normalized": "6.0.19.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "db5416d04269f2827d8c54331ba4cfa42620d350" + "reference": "df56f53818c2d5d9f683f4ad2e365ba73a3b69d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/db5416d04269f2827d8c54331ba4cfa42620d350", - "reference": "db5416d04269f2827d8c54331ba4cfa42620d350", - "shasum": "" + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df56f53818c2d5d9f683f4ad2e365ba73a3b69d2", + "reference": "df56f53818c2d5d9f683f4ad2e365ba73a3b69d2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { - "php": ">=8.1" + "php": ">=8.0.2" }, "require-dev": { "symfony/var-dumper": "^5.4|^6.0" }, - "time": "2023-04-21T08:48:44+00:00", + "time": "2023-01-13T08:34:10+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4134,12 +4262,10 @@ "export", "hydrate", "instantiate", - "lazy-loading", - "proxy", "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.3.0" + "source": "https://github.com/symfony/var-exporter/tree/v6.0.19" }, "funding": [ { @@ -4732,18 +4858,24 @@ }, { "name": "w7corp/easywechat", - "version": "6.12.3", - "version_normalized": "6.12.3.0", + "version": "6.8.0", + "version_normalized": "6.8.0.0", "source": { "type": "git", "url": "https://github.com/w7corp/easywechat.git", - "reference": "10b9f31b61b4e5327c9e4457dffcf307de2deb6c" + "reference": "60f0b4ba2ac3144df1a2291193daa34beb949d26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/w7corp/easywechat/zipball/10b9f31b61b4e5327c9e4457dffcf307de2deb6c", - "reference": "10b9f31b61b4e5327c9e4457dffcf307de2deb6c", - "shasum": "" + "url": "https://api.github.com/repos/w7corp/easywechat/zipball/60f0b4ba2ac3144df1a2291193daa34beb949d26", + "reference": "60f0b4ba2ac3144df1a2291193daa34beb949d26", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] }, "require": { "ext-curl": "*", @@ -4752,10 +4884,10 @@ "ext-openssl": "*", "ext-simplexml": "*", "ext-sodium": "*", - "monolog/monolog": "^2.2|^3.0", + "monolog/monolog": "^2.2", "nyholm/psr7": "^1.5", "nyholm/psr7-server": "^1.0", - "overtrue/socialite": "^3.5.4|^4.0.1", + "overtrue/socialite": "^3.5|^4.0.1", "php": ">=8.0.2", "psr/http-client": "^1.0", "psr/simple-cache": "^1.0|^2.0|^3.0", @@ -4777,7 +4909,7 @@ "phpunit/phpunit": "^9.5", "symfony/var-dumper": "^5.2" }, - "time": "2023-07-05T14:14:28+00:00", + "time": "2022-09-25T13:05:18+00:00", "type": "library", "extra": { "hooks": { @@ -4823,7 +4955,7 @@ ], "support": { "issues": "https://github.com/w7corp/easywechat/issues", - "source": "https://github.com/w7corp/easywechat/tree/6.12.3" + "source": "https://github.com/w7corp/easywechat/tree/6.8.0" }, "funding": [ { diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 35beef7ed..59b3f52e5 100755 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'topthink/think', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'b55f77d5c3e94177ec3d1ce21fce629a756733b6', + 'reference' => '942e2b120398de55e20eaf3f36f1dab679db2c41', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -47,9 +47,9 @@ 'dev_requirement' => false, ), 'dragonmantank/cron-expression' => array( - 'pretty_version' => 'v3.3.2', - 'version' => '3.3.2.0', - 'reference' => '782ca5968ab8b954773518e9e49a6f892a34b2a8', + 'pretty_version' => 'v3.3.1', + 'version' => '3.3.1.0', + 'reference' => 'be85b3f05b46c39bbc0d95f6c071ddff669510fa', 'type' => 'library', 'install_path' => __DIR__ . '/../dragonmantank/cron-expression', 'aliases' => array(), @@ -101,9 +101,9 @@ 'dev_requirement' => false, ), 'guzzlehttp/promises' => array( - 'pretty_version' => '2.0.0', - 'version' => '2.0.0.0', - 'reference' => '3a494dc7dc1d7d12e511890177ae2d0e6c107da6', + 'pretty_version' => '1.5.3', + 'version' => '1.5.3.0', + 'reference' => '67ab6e18aaa14d753cc148911d273f6e6cb6721e', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/promises', 'aliases' => array(), @@ -128,9 +128,9 @@ 'dev_requirement' => false, ), 'maennchen/zipstream-php' => array( - 'pretty_version' => '3.1.0', - 'version' => '3.1.0.0', - 'reference' => 'b8174494eda667f7d13876b4a7bfef0f62a7c0d1', + 'pretty_version' => '2.4.0', + 'version' => '2.4.0.0', + 'reference' => '3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3', 'type' => 'library', 'install_path' => __DIR__ . '/../maennchen/zipstream-php', 'aliases' => array(), @@ -178,6 +178,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'myclabs/php-enum' => array( + 'pretty_version' => '1.8.3', + 'version' => '1.8.3.0', + 'reference' => 'b942d263c641ddb5190929ff840c68f78713e937', + 'type' => 'library', + 'install_path' => __DIR__ . '/../myclabs/php-enum', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'nyholm/psr7' => array( 'pretty_version' => '1.8.0', 'version' => '1.8.0.0', @@ -224,9 +233,9 @@ ), ), 'phpoffice/phpspreadsheet' => array( - 'pretty_version' => '1.29.0', - 'version' => '1.29.0.0', - 'reference' => 'fde2ccf55eaef7e86021ff1acce26479160a0fa0', + 'pretty_version' => '1.28.0', + 'version' => '1.28.0.0', + 'reference' => '6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a', 'type' => 'library', 'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet', 'aliases' => array(), @@ -257,9 +266,9 @@ 'dev_requirement' => false, ), 'psr/http-client' => array( - 'pretty_version' => '1.0.2', - 'version' => '1.0.2.0', - 'reference' => '0955afe48220520692d2d09f7ab7e0f93ffd6a31', + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-client', 'aliases' => array(), @@ -359,9 +368,9 @@ 'dev_requirement' => false, ), 'rmccue/requests' => array( - 'pretty_version' => 'v2.0.7', - 'version' => '2.0.7.0', - 'reference' => 'e14a6f4e7438d3f8da3f2657759e6367b906ee23', + 'pretty_version' => 'v2.0.5', + 'version' => '2.0.5.0', + 'reference' => 'b717f1d2f4ef7992ec0c127747ed8b7e170c2f49', 'type' => 'library', 'install_path' => __DIR__ . '/../rmccue/requests', 'aliases' => array(), @@ -392,27 +401,27 @@ ), ), 'symfony/deprecation-contracts' => array( - 'pretty_version' => 'v3.3.0', - 'version' => '3.3.0.0', - 'reference' => '7c3aff79d10325257a001fcf92d991f24fc967cf', + 'pretty_version' => 'v3.0.2', + 'version' => '3.0.2.0', + 'reference' => '26954b3d62a6c5fd0ea8a2a00c0353a14978d05c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/http-client' => array( - 'pretty_version' => 'v6.2.12', - 'version' => '6.2.12.0', - 'reference' => '7ef37b91629937843e8f52a2da5587ff16d75d25', + 'pretty_version' => 'v6.0.20', + 'version' => '6.0.20.0', + 'reference' => '541c04560da1875f62c963c3aab6ea12a7314e11', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-client', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/http-client-contracts' => array( - 'pretty_version' => 'v3.3.0', - 'version' => '3.3.0.0', - 'reference' => '3b66325d0176b4ec826bffab57c9037d759c31fb', + 'pretty_version' => 'v3.0.2', + 'version' => '3.0.2.0', + 'reference' => '4184b9b63af1edaf35b6a7974c6f1f9f33294129', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-client-contracts', 'aliases' => array(), @@ -425,18 +434,18 @@ ), ), 'symfony/http-foundation' => array( - 'pretty_version' => 'v6.1.12', - 'version' => '6.1.12.0', - 'reference' => 'bd1bcfb0eba14de22c4d086c5023e608f37366ed', + 'pretty_version' => 'v6.0.20', + 'version' => '6.0.20.0', + 'reference' => 'e16b2676a4b3b1fa12378a20b29c364feda2a8d6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/mime' => array( - 'pretty_version' => 'v6.3.0', - 'version' => '6.3.0.0', - 'reference' => '7b5d2121858cd6efbed778abce9cfdd7ab1f62ad', + 'pretty_version' => 'v6.0.19', + 'version' => '6.0.19.0', + 'reference' => 'd7052547a0070cbeadd474e172b527a00d657301', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/mime', 'aliases' => array(), @@ -542,9 +551,9 @@ 'dev_requirement' => true, ), 'symfony/var-exporter' => array( - 'pretty_version' => 'v6.3.0', - 'version' => '6.3.0.0', - 'reference' => 'db5416d04269f2827d8c54331ba4cfa42620d350', + 'pretty_version' => 'v6.0.19', + 'version' => '6.0.19.0', + 'reference' => 'df56f53818c2d5d9f683f4ad2e365ba73a3b69d2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-exporter', 'aliases' => array(), @@ -589,7 +598,7 @@ 'topthink/think' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'b55f77d5c3e94177ec3d1ce21fce629a756733b6', + 'reference' => '942e2b120398de55e20eaf3f36f1dab679db2c41', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -650,9 +659,9 @@ 'dev_requirement' => false, ), 'w7corp/easywechat' => array( - 'pretty_version' => '6.12.3', - 'version' => '6.12.3.0', - 'reference' => '10b9f31b61b4e5327c9e4457dffcf307de2deb6c', + 'pretty_version' => '6.8.0', + 'version' => '6.8.0.0', + 'reference' => '60f0b4ba2ac3144df1a2291193daa34beb949d26', 'type' => 'library', 'install_path' => __DIR__ . '/../w7corp/easywechat', 'aliases' => array(), diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php index 4c3a5d68f..b168ddd5d 100755 --- a/vendor/composer/platform_check.php +++ b/vendor/composer/platform_check.php @@ -4,8 +4,8 @@ $issues = array(); -if (!(PHP_VERSION_ID >= 80100)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.'; +if (!(PHP_VERSION_ID >= 80002)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.2". You are running ' . PHP_VERSION . '.'; } if ($issues) { diff --git a/vendor/dragonmantank/cron-expression/CHANGELOG.md b/vendor/dragonmantank/cron-expression/CHANGELOG.md index 7b6df4b1c..99b587be1 100644 --- a/vendor/dragonmantank/cron-expression/CHANGELOG.md +++ b/vendor/dragonmantank/cron-expression/CHANGELOG.md @@ -1,16 +1,5 @@ # Change Log -## [3.3.2] - 2022-09-19 - -### Added -- N/A - -### Changed -- Skip some daylight savings time tests for PHP 8.1 daylight savings time weirdness (#146) - -### Fixed -- Changed string interpolations to work better with PHP 8.2 (#142) - ## [3.3.1] - 2022-01-18 ### Added diff --git a/vendor/dragonmantank/cron-expression/composer.json b/vendor/dragonmantank/cron-expression/composer.json index 657a5b47c..e512446d1 100644 --- a/vendor/dragonmantank/cron-expression/composer.json +++ b/vendor/dragonmantank/cron-expression/composer.json @@ -37,11 +37,5 @@ "scripts": { "phpstan": "./vendor/bin/phpstan analyze", "test": "phpunit" - }, - "config": { - "allow-plugins": { - "ocramius/package-versions": true, - "phpstan/extension-installer": true - } } } diff --git a/vendor/dragonmantank/cron-expression/src/Cron/DayOfMonthField.php b/vendor/dragonmantank/cron-expression/src/Cron/DayOfMonthField.php index 39ff59783..e08f62ead 100644 --- a/vendor/dragonmantank/cron-expression/src/Cron/DayOfMonthField.php +++ b/vendor/dragonmantank/cron-expression/src/Cron/DayOfMonthField.php @@ -49,7 +49,7 @@ class DayOfMonthField extends AbstractField private static function getNearestWeekday(int $currentYear, int $currentMonth, int $targetDay): ?DateTime { $tday = str_pad((string) $targetDay, 2, '0', STR_PAD_LEFT); - $target = DateTime::createFromFormat('Y-m-d', "{$currentYear}-{$currentMonth}-{$tday}"); + $target = DateTime::createFromFormat('Y-m-d', "${currentYear}-${currentMonth}-${tday}"); if ($target === false) { return null; @@ -94,9 +94,9 @@ class DayOfMonthField extends AbstractField } // Check to see if this is the nearest weekday to a particular value - if ($wPosition = strpos($value, 'W')) { + if (strpos($value, 'W')) { // Parse the target day - $targetDay = (int) substr($value, 0, $wPosition); + $targetDay = (int) substr($value, 0, strpos($value, 'W')); // Find out if the current day is the nearest day of the week $nearest = self::getNearestWeekday( (int) $date->format('Y'), diff --git a/vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php b/vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php index b9bbf48b6..5ac003da9 100644 --- a/vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php +++ b/vendor/dragonmantank/cron-expression/src/Cron/DayOfWeekField.php @@ -68,8 +68,8 @@ class DayOfWeekField extends AbstractField $lastDayOfMonth = (int) $date->format('t'); // Find out if this is the last specific weekday of the month - if ($lPosition = strpos($value, 'L')) { - $weekday = $this->convertLiterals(substr($value, 0, $lPosition)); + if (strpos($value, 'L')) { + $weekday = $this->convertLiterals(substr($value, 0, strpos($value, 'L'))); $weekday %= 7; $daysInMonth = (int) $date->format('t'); diff --git a/vendor/dragonmantank/cron-expression/src/Cron/HoursField.php b/vendor/dragonmantank/cron-expression/src/Cron/HoursField.php index 413d138be..a7f8f33c4 100644 --- a/vendor/dragonmantank/cron-expression/src/Cron/HoursField.php +++ b/vendor/dragonmantank/cron-expression/src/Cron/HoursField.php @@ -25,7 +25,7 @@ class HoursField extends AbstractField /** * @var array|null Transitions returned by DateTimeZone::getTransitions() */ - protected $transitions = []; + protected $transitions = null; /** * @var int|null Timestamp of the start of the transitions range @@ -92,7 +92,7 @@ class HoursField extends AbstractField $dtLimitStart->getTimestamp(), $dtLimitEnd->getTimestamp() ); - if (empty($this->transitions)) { + if ($this->transitions === false) { return null; } $this->transitionsStart = $dtLimitStart->getTimestamp(); diff --git a/vendor/guzzlehttp/promises/CHANGELOG.md b/vendor/guzzlehttp/promises/CHANGELOG.md index ab173ad74..2e1a2f384 100644 --- a/vendor/guzzlehttp/promises/CHANGELOG.md +++ b/vendor/guzzlehttp/promises/CHANGELOG.md @@ -1,36 +1,17 @@ # CHANGELOG - -## 2.0.0 - TBC - -### Added - -- Added PHP 7 type hints - -### Changed - -- All previously non-final non-exception classes have been marked as soft-final - -### Removed - -- Dropped PHP < 7.2 support -- All functions in the `GuzzleHttp\Promise` namespace - - ## 1.5.3 - 2023-05-21 ### Changed - Removed remaining usage of deprecated functions - ## 1.5.2 - 2022-08-07 ### Changed - Officially support PHP 8.2 - ## 1.5.1 - 2021-10-22 ### Fixed @@ -38,7 +19,6 @@ - Revert "Call handler when waiting on fulfilled/rejected Promise" - Fix pool memory leak when empty array of promises provided - ## 1.5.0 - 2021-10-07 ### Changed @@ -50,14 +30,12 @@ - Fix manually settle promises generated with `Utils::task` - ## 1.4.1 - 2021-02-18 ### Fixed - Fixed `each_limit` skipping promises and failing - ## 1.4.0 - 2020-09-30 ### Added diff --git a/vendor/guzzlehttp/promises/README.md b/vendor/guzzlehttp/promises/README.md index 4dc7b6a1d..1ea667ab9 100644 --- a/vendor/guzzlehttp/promises/README.md +++ b/vendor/guzzlehttp/promises/README.md @@ -29,21 +29,6 @@ for a general introduction to promises. `GuzzleHttp\Promise\Coroutine::of()`. -## Installation - -```shell -composer require guzzlehttp/promises -``` - - -## Version Guidance - -| Version | Status | PHP Version | -|---------|------------------------|--------------| -| 1.x | Bug and security fixes | >=5.5,<8.3 | -| 2.x | Latest | >=7.2.5,<8.3 | - - ## Quick Start A *promise* represents the eventual result of an asynchronous operation. The @@ -445,6 +430,8 @@ $loop = React\EventLoop\Factory::create(); $loop->addPeriodicTimer(0, [$queue, 'run']); ``` +*TODO*: Perhaps adding a `futureTick()` on each tick would be faster? + ## Implementation Notes @@ -514,8 +501,8 @@ $promise->resolve('foo'); A static API was first introduced in 1.4.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The -function API was removed in 2.0.0. A migration table has been provided here for -your convenience: +function API will be removed in 2.0.0. A migration table has been provided here +for your convenience: | Original Function | Replacement Method | |----------------|----------------| diff --git a/vendor/guzzlehttp/promises/composer.json b/vendor/guzzlehttp/promises/composer.json index fc1989ec1..966e3e3a8 100644 --- a/vendor/guzzlehttp/promises/composer.json +++ b/vendor/guzzlehttp/promises/composer.json @@ -26,32 +26,27 @@ } ], "require": { - "php": "^7.2.5 || ^8.0" + "php": ">=5.5" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "symfony/phpunit-bridge": "^4.4 || ^5.1" }, "autoload": { "psr-4": { "GuzzleHttp\\Promise\\": "src/" - } + }, + "files": ["src/functions_include.php"] }, "autoload-dev": { "psr-4": { "GuzzleHttp\\Promise\\Tests\\": "tests/" } }, - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } + "scripts": { + "test": "vendor/bin/simple-phpunit", + "test-ci": "vendor/bin/simple-phpunit --coverage-text" }, "config": { - "allow-plugins": { - "bamarni/composer-bin-plugin": true - }, "preferred-install": "dist", "sort-packages": true } diff --git a/vendor/guzzlehttp/promises/src/AggregateException.php b/vendor/guzzlehttp/promises/src/AggregateException.php index 40ffdbcf1..d2b5712b9 100644 --- a/vendor/guzzlehttp/promises/src/AggregateException.php +++ b/vendor/guzzlehttp/promises/src/AggregateException.php @@ -1,7 +1,5 @@ generator = $generatorFn(); - $this->result = new Promise(function (): void { + $this->result = new Promise(function () { while (isset($this->currentPromise)) { $this->currentPromise->wait(); } }); try { $this->nextCoroutine($this->generator->current()); + } catch (\Exception $exception) { + $this->result->reject($exception); } catch (Throwable $throwable) { $this->result->reject($throwable); } @@ -77,8 +78,10 @@ final class Coroutine implements PromiseInterface /** * Create a new coroutine. + * + * @return self */ - public static function of(callable $generatorFn): self + public static function of(callable $generatorFn) { return new self($generatorFn); } @@ -86,42 +89,42 @@ final class Coroutine implements PromiseInterface public function then( callable $onFulfilled = null, callable $onRejected = null - ): PromiseInterface { + ) { return $this->result->then($onFulfilled, $onRejected); } - public function otherwise(callable $onRejected): PromiseInterface + public function otherwise(callable $onRejected) { return $this->result->otherwise($onRejected); } - public function wait(bool $unwrap = true) + public function wait($unwrap = true) { return $this->result->wait($unwrap); } - public function getState(): string + public function getState() { return $this->result->getState(); } - public function resolve($value): void + public function resolve($value) { $this->result->resolve($value); } - public function reject($reason): void + public function reject($reason) { $this->result->reject($reason); } - public function cancel(): void + public function cancel() { $this->currentPromise->cancel(); $this->result->cancel(); } - private function nextCoroutine($yielded): void + private function nextCoroutine($yielded) { $this->currentPromise = Create::promiseFor($yielded) ->then([$this, '_handleSuccess'], [$this, '_handleFailure']); @@ -130,7 +133,7 @@ final class Coroutine implements PromiseInterface /** * @internal */ - public function _handleSuccess($value): void + public function _handleSuccess($value) { unset($this->currentPromise); try { @@ -140,6 +143,8 @@ final class Coroutine implements PromiseInterface } else { $this->result->resolve($value); } + } catch (Exception $exception) { + $this->result->reject($exception); } catch (Throwable $throwable) { $this->result->reject($throwable); } @@ -148,13 +153,15 @@ final class Coroutine implements PromiseInterface /** * @internal */ - public function _handleFailure($reason): void + public function _handleFailure($reason) { unset($this->currentPromise); try { $nextYield = $this->generator->throw(Create::exceptionFor($reason)); // The throw was caught, so keep iterating on the coroutine $this->nextCoroutine($nextYield); + } catch (Exception $exception) { + $this->result->reject($exception); } catch (Throwable $throwable) { $this->result->reject($throwable); } diff --git a/vendor/guzzlehttp/promises/src/Create.php b/vendor/guzzlehttp/promises/src/Create.php index 9d3fc4a1e..8d038e9c1 100644 --- a/vendor/guzzlehttp/promises/src/Create.php +++ b/vendor/guzzlehttp/promises/src/Create.php @@ -1,7 +1,5 @@ then([$promise, 'resolve'], [$promise, 'reject']); - return $promise; } @@ -35,8 +34,10 @@ final class Create * If the provided reason is a promise, then it is returned as-is. * * @param mixed $reason Promise or reason. + * + * @return PromiseInterface */ - public static function rejectionFor($reason): PromiseInterface + public static function rejectionFor($reason) { if ($reason instanceof PromiseInterface) { return $reason; @@ -49,10 +50,12 @@ final class Create * Create an exception for a rejected promise value. * * @param mixed $reason + * + * @return \Exception|\Throwable */ - public static function exceptionFor($reason): \Throwable + public static function exceptionFor($reason) { - if ($reason instanceof \Throwable) { + if ($reason instanceof \Exception || $reason instanceof \Throwable) { return $reason; } @@ -63,8 +66,10 @@ final class Create * Returns an iterator for the given value. * * @param mixed $value + * + * @return \Iterator */ - public static function iterFor($value): \Iterator + public static function iterFor($value) { if ($value instanceof \Iterator) { return $value; diff --git a/vendor/guzzlehttp/promises/src/Each.php b/vendor/guzzlehttp/promises/src/Each.php index 1a7aa0fb6..ff8efd734 100644 --- a/vendor/guzzlehttp/promises/src/Each.php +++ b/vendor/guzzlehttp/promises/src/Each.php @@ -1,7 +1,5 @@ $onFulfilled, - 'rejected' => $onRejected, + 'rejected' => $onRejected ]))->promise(); } @@ -46,17 +46,19 @@ final class Each * @param int|callable $concurrency * @param callable $onFulfilled * @param callable $onRejected + * + * @return PromiseInterface */ public static function ofLimit( $iterable, $concurrency, callable $onFulfilled = null, callable $onRejected = null - ): PromiseInterface { + ) { return (new EachPromise($iterable, [ - 'fulfilled' => $onFulfilled, - 'rejected' => $onRejected, - 'concurrency' => $concurrency, + 'fulfilled' => $onFulfilled, + 'rejected' => $onRejected, + 'concurrency' => $concurrency ]))->promise(); } @@ -68,17 +70,19 @@ final class Each * @param mixed $iterable * @param int|callable $concurrency * @param callable $onFulfilled + * + * @return PromiseInterface */ public static function ofLimitAll( $iterable, $concurrency, callable $onFulfilled = null - ): PromiseInterface { + ) { return self::ofLimit( $iterable, $concurrency, $onFulfilled, - function ($reason, $idx, PromiseInterface $aggregate): void { + function ($reason, $idx, PromiseInterface $aggregate) { $aggregate->reject($reason); } ); diff --git a/vendor/guzzlehttp/promises/src/EachPromise.php b/vendor/guzzlehttp/promises/src/EachPromise.php index 28dd9793a..280d79950 100644 --- a/vendor/guzzlehttp/promises/src/EachPromise.php +++ b/vendor/guzzlehttp/promises/src/EachPromise.php @@ -1,14 +1,10 @@ aggregate) { return $this->aggregate; @@ -86,18 +82,21 @@ class EachPromise implements PromisorInterface $this->refillPending(); } catch (\Throwable $e) { $this->aggregate->reject($e); + } catch (\Exception $e) { + $this->aggregate->reject($e); } /** * @psalm-suppress NullableReturnStatement + * @phpstan-ignore-next-line */ return $this->aggregate; } - private function createPromise(): void + private function createPromise() { $this->mutex = false; - $this->aggregate = new Promise(function (): void { + $this->aggregate = new Promise(function () { if ($this->checkIfFinished()) { return; } @@ -114,7 +113,7 @@ class EachPromise implements PromisorInterface }); // Clear the references when the promise is resolved. - $clearFn = function (): void { + $clearFn = function () { $this->iterable = $this->concurrency = $this->pending = null; $this->onFulfilled = $this->onRejected = null; $this->nextPendingIndex = 0; @@ -123,13 +122,11 @@ class EachPromise implements PromisorInterface $this->aggregate->then($clearFn, $clearFn); } - private function refillPending(): void + private function refillPending() { if (!$this->concurrency) { // Add all pending promises. - while ($this->addPending() && $this->advanceIterator()) { - } - + while ($this->addPending() && $this->advanceIterator()); return; } @@ -150,11 +147,10 @@ class EachPromise implements PromisorInterface // next value to yield until promise callbacks are called. while (--$concurrency && $this->advanceIterator() - && $this->addPending()) { - } + && $this->addPending()); } - private function addPending(): bool + private function addPending() { if (!$this->iterable || !$this->iterable->valid()) { return false; @@ -168,7 +164,7 @@ class EachPromise implements PromisorInterface $idx = $this->nextPendingIndex++; $this->pending[$idx] = $promise->then( - function ($value) use ($idx, $key): void { + function ($value) use ($idx, $key) { if ($this->onFulfilled) { call_user_func( $this->onFulfilled, @@ -179,7 +175,7 @@ class EachPromise implements PromisorInterface } $this->step($idx); }, - function ($reason) use ($idx, $key): void { + function ($reason) use ($idx, $key) { if ($this->onRejected) { call_user_func( $this->onRejected, @@ -195,7 +191,7 @@ class EachPromise implements PromisorInterface return true; } - private function advanceIterator(): bool + private function advanceIterator() { // Place a lock on the iterator so that we ensure to not recurse, // preventing fatal generator errors. @@ -208,17 +204,19 @@ class EachPromise implements PromisorInterface try { $this->iterable->next(); $this->mutex = false; - return true; } catch (\Throwable $e) { $this->aggregate->reject($e); $this->mutex = false; - + return false; + } catch (\Exception $e) { + $this->aggregate->reject($e); + $this->mutex = false; return false; } } - private function step(int $idx): void + private function step($idx) { // If the promise was already resolved, then ignore this step. if (Is::settled($this->aggregate)) { @@ -236,12 +234,11 @@ class EachPromise implements PromisorInterface } } - private function checkIfFinished(): bool + private function checkIfFinished() { if (!$this->pending && !$this->iterable->valid()) { // Resolve the promise if there's nothing left to do. $this->aggregate->resolve(null); - return true; } diff --git a/vendor/guzzlehttp/promises/src/FulfilledPromise.php b/vendor/guzzlehttp/promises/src/FulfilledPromise.php index ab7129659..98f72a62a 100644 --- a/vendor/guzzlehttp/promises/src/FulfilledPromise.php +++ b/vendor/guzzlehttp/promises/src/FulfilledPromise.php @@ -1,7 +1,5 @@ value; - $queue->add(static function () use ($p, $value, $onFulfilled): void { + $queue->add(static function () use ($p, $value, $onFulfilled) { if (Is::pending($p)) { try { $p->resolve($onFulfilled($value)); } catch (\Throwable $e) { $p->reject($e); + } catch (\Exception $e) { + $p->reject($e); } } }); @@ -55,34 +50,34 @@ class FulfilledPromise implements PromiseInterface return $p; } - public function otherwise(callable $onRejected): PromiseInterface + public function otherwise(callable $onRejected) { return $this->then(null, $onRejected); } - public function wait(bool $unwrap = true) + public function wait($unwrap = true, $defaultDelivery = null) { return $unwrap ? $this->value : null; } - public function getState(): string + public function getState() { return self::FULFILLED; } - public function resolve($value): void + public function resolve($value) { if ($value !== $this->value) { - throw new \LogicException('Cannot resolve a fulfilled promise'); + throw new \LogicException("Cannot resolve a fulfilled promise"); } } - public function reject($reason): void + public function reject($reason) { - throw new \LogicException('Cannot reject a fulfilled promise'); + throw new \LogicException("Cannot reject a fulfilled promise"); } - public function cancel(): void + public function cancel() { // pass } diff --git a/vendor/guzzlehttp/promises/src/Is.php b/vendor/guzzlehttp/promises/src/Is.php index f3f050384..c3ed8d014 100644 --- a/vendor/guzzlehttp/promises/src/Is.php +++ b/vendor/guzzlehttp/promises/src/Is.php @@ -1,39 +1,45 @@ getState() === PromiseInterface::PENDING; } /** * Returns true if a promise is fulfilled or rejected. + * + * @return bool */ - public static function settled(PromiseInterface $promise): bool + public static function settled(PromiseInterface $promise) { return $promise->getState() !== PromiseInterface::PENDING; } /** * Returns true if a promise is fulfilled. + * + * @return bool */ - public static function fulfilled(PromiseInterface $promise): bool + public static function fulfilled(PromiseInterface $promise) { return $promise->getState() === PromiseInterface::FULFILLED; } /** * Returns true if a promise is rejected. + * + * @return bool */ - public static function rejected(PromiseInterface $promise): bool + public static function rejected(PromiseInterface $promise) { return $promise->getState() === PromiseInterface::REJECTED; } diff --git a/vendor/guzzlehttp/promises/src/Promise.php b/vendor/guzzlehttp/promises/src/Promise.php index 1b07bdc9a..75939057b 100644 --- a/vendor/guzzlehttp/promises/src/Promise.php +++ b/vendor/guzzlehttp/promises/src/Promise.php @@ -1,15 +1,11 @@ state === self::PENDING) { $p = new Promise(null, [$this, 'cancel']); $this->handlers[] = [$p, $onFulfilled, $onRejected]; $p->waitList = $this->waitList; $p->waitList[] = $this; - return $p; } // Return a fulfilled promise and immediately invoke any callbacks. if ($this->state === self::FULFILLED) { $promise = Create::promiseFor($this->result); - return $onFulfilled ? $promise->then($onFulfilled) : $promise; } // It's either cancelled or rejected, so return a rejected promise // and immediately invoke any callbacks. $rejection = Create::rejectionFor($this->result); - return $onRejected ? $rejection->then(null, $onRejected) : $rejection; } - public function otherwise(callable $onRejected): PromiseInterface + public function otherwise(callable $onRejected) { return $this->then(null, $onRejected); } - public function wait(bool $unwrap = true) + public function wait($unwrap = true) { $this->waitIfPending(); @@ -80,12 +73,12 @@ class Promise implements PromiseInterface } } - public function getState(): string + public function getState() { return $this->state; } - public function cancel(): void + public function cancel() { if ($this->state !== self::PENDING) { return; @@ -100,6 +93,8 @@ class Promise implements PromiseInterface $fn(); } catch (\Throwable $e) { $this->reject($e); + } catch (\Exception $e) { + $this->reject($e); } } @@ -110,17 +105,17 @@ class Promise implements PromiseInterface } } - public function resolve($value): void + public function resolve($value) { $this->settle(self::FULFILLED, $value); } - public function reject($reason): void + public function reject($reason) { $this->settle(self::REJECTED, $reason); } - private function settle(string $state, $value): void + private function settle($state, $value) { if ($this->state !== self::PENDING) { // Ignore calls with the same resolution. @@ -153,7 +148,7 @@ class Promise implements PromiseInterface if (!is_object($value) || !method_exists($value, 'then')) { $id = $state === self::FULFILLED ? 1 : 2; // It's a success, so resolve the handlers in the queue. - Utils::queue()->add(static function () use ($id, $value, $handlers): void { + Utils::queue()->add(static function () use ($id, $value, $handlers) { foreach ($handlers as $handler) { self::callHandler($id, $value, $handler); } @@ -164,12 +159,12 @@ class Promise implements PromiseInterface } else { // Resolve the handlers when the forwarded promise is resolved. $value->then( - static function ($value) use ($handlers): void { + static function ($value) use ($handlers) { foreach ($handlers as $handler) { self::callHandler(1, $value, $handler); } }, - static function ($reason) use ($handlers): void { + static function ($reason) use ($handlers) { foreach ($handlers as $handler) { self::callHandler(2, $reason, $handler); } @@ -185,7 +180,7 @@ class Promise implements PromiseInterface * @param mixed $value Value to pass to the callback. * @param array $handler Array of handler data (promise and callbacks). */ - private static function callHandler(int $index, $value, array $handler): void + private static function callHandler($index, $value, array $handler) { /** @var PromiseInterface $promise */ $promise = $handler[0]; @@ -216,10 +211,12 @@ class Promise implements PromiseInterface } } catch (\Throwable $reason) { $promise->reject($reason); + } catch (\Exception $reason) { + $promise->reject($reason); } } - private function waitIfPending(): void + private function waitIfPending() { if ($this->state !== self::PENDING) { return; @@ -230,9 +227,9 @@ class Promise implements PromiseInterface } else { // If there's no 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 ' - .'wait on a promise.'); + . 'no internal wait function. You must provide a wait ' + . 'function when constructing the promise to be able to ' + . 'wait on a promise.'); } Utils::queue()->run(); @@ -243,13 +240,13 @@ class Promise implements PromiseInterface } } - private function invokeWaitFn(): void + private function invokeWaitFn() { try { $wfn = $this->waitFn; $this->waitFn = null; $wfn(true); - } catch (\Throwable $reason) { + } catch (\Exception $reason) { if ($this->state === self::PENDING) { // The promise has not been resolved yet, so reject the promise // with the exception. @@ -262,7 +259,7 @@ class Promise implements PromiseInterface } } - private function invokeWaitList(): void + private function invokeWaitList() { $waitList = $this->waitList; $this->waitList = null; diff --git a/vendor/guzzlehttp/promises/src/PromiseInterface.php b/vendor/guzzlehttp/promises/src/PromiseInterface.php index 2824802bb..e59833143 100644 --- a/vendor/guzzlehttp/promises/src/PromiseInterface.php +++ b/vendor/guzzlehttp/promises/src/PromiseInterface.php @@ -1,7 +1,5 @@ reason; $p = new Promise([$queue, 'run']); - $queue->add(static function () use ($p, $reason, $onRejected): void { + $queue->add(static function () use ($p, $reason, $onRejected) { if (Is::pending($p)) { try { // Return a resolved promise if onRejected does not throw. @@ -50,6 +43,9 @@ class RejectedPromise implements PromiseInterface } catch (\Throwable $e) { // onRejected threw, so return a rejected promise. $p->reject($e); + } catch (\Exception $e) { + // onRejected threw, so return a rejected promise. + $p->reject($e); } } }); @@ -57,12 +53,12 @@ class RejectedPromise implements PromiseInterface return $p; } - public function otherwise(callable $onRejected): PromiseInterface + public function otherwise(callable $onRejected) { return $this->then(null, $onRejected); } - public function wait(bool $unwrap = true) + public function wait($unwrap = true, $defaultDelivery = null) { if ($unwrap) { throw Create::exceptionFor($this->reason); @@ -71,24 +67,24 @@ class RejectedPromise implements PromiseInterface return null; } - public function getState(): string + public function getState() { return self::REJECTED; } - public function resolve($value): void + public function resolve($value) { - throw new \LogicException('Cannot resolve a rejected promise'); + throw new \LogicException("Cannot resolve a rejected promise"); } - public function reject($reason): void + public function reject($reason) { if ($reason !== $this->reason) { - throw new \LogicException('Cannot reject a rejected promise'); + throw new \LogicException("Cannot reject a rejected promise"); } } - public function cancel(): void + public function cancel() { // pass } diff --git a/vendor/guzzlehttp/promises/src/RejectionException.php b/vendor/guzzlehttp/promises/src/RejectionException.php index 0db98ffb9..e2f137707 100644 --- a/vendor/guzzlehttp/promises/src/RejectionException.php +++ b/vendor/guzzlehttp/promises/src/RejectionException.php @@ -1,7 +1,5 @@ reason; + $message .= ' with reason: ' . $this->reason; } elseif ($reason instanceof \JsonSerializable) { - $message .= ' with reason: '.json_encode($this->reason, JSON_PRETTY_PRINT); + $message .= ' with reason: ' + . json_encode($this->reason, JSON_PRETTY_PRINT); } parent::__construct($message); diff --git a/vendor/guzzlehttp/promises/src/TaskQueue.php b/vendor/guzzlehttp/promises/src/TaskQueue.php index 503e0b2da..f0fba2c59 100644 --- a/vendor/guzzlehttp/promises/src/TaskQueue.php +++ b/vendor/guzzlehttp/promises/src/TaskQueue.php @@ -1,7 +1,5 @@ run(); - * - * @final */ class TaskQueue implements TaskQueueInterface { private $enableShutdown = true; private $queue = []; - public function __construct(bool $withShutdown = true) + public function __construct($withShutdown = true) { if ($withShutdown) { - register_shutdown_function(function (): void { + register_shutdown_function(function () { if ($this->enableShutdown) { // Only run the tasks if an E_ERROR didn't occur. $err = error_get_last(); @@ -35,17 +31,17 @@ class TaskQueue implements TaskQueueInterface } } - public function isEmpty(): bool + public function isEmpty() { return !$this->queue; } - public function add(callable $task): void + public function add(callable $task) { $this->queue[] = $task; } - public function run(): void + public function run() { while ($task = array_shift($this->queue)) { /** @var callable $task */ @@ -64,7 +60,7 @@ class TaskQueue implements TaskQueueInterface * * Note: This shutdown will occur before any destructors are triggered. */ - public function disableShutdown(): void + public function disableShutdown() { $this->enableShutdown = false; } diff --git a/vendor/guzzlehttp/promises/src/TaskQueueInterface.php b/vendor/guzzlehttp/promises/src/TaskQueueInterface.php index 34c561a48..723d4d54e 100644 --- a/vendor/guzzlehttp/promises/src/TaskQueueInterface.php +++ b/vendor/guzzlehttp/promises/src/TaskQueueInterface.php @@ -1,24 +1,24 @@ * - * @param TaskQueueInterface|null $assign Optionally specify a new queue instance. + * @param TaskQueueInterface $assign Optionally specify a new queue instance. + * + * @return TaskQueueInterface */ - public static function queue(TaskQueueInterface $assign = null): TaskQueueInterface + public static function queue(TaskQueueInterface $assign = null) { static $queue; @@ -39,18 +39,22 @@ final class Utils * returns a promise that is fulfilled or rejected with the result. * * @param callable $task Task function to run. + * + * @return PromiseInterface */ - public static function task(callable $task): PromiseInterface + public static function task(callable $task) { $queue = self::queue(); $promise = new Promise([$queue, 'run']); - $queue->add(function () use ($task, $promise): void { + $queue->add(function () use ($task, $promise) { try { if (Is::pending($promise)) { $promise->resolve($task()); } } catch (\Throwable $e) { $promise->reject($e); + } catch (\Exception $e) { + $promise->reject($e); } }); @@ -68,18 +72,22 @@ final class Utils * key mapping to the rejection reason of the promise. * * @param PromiseInterface $promise Promise or value. + * + * @return array */ - public static function inspect(PromiseInterface $promise): array + public static function inspect(PromiseInterface $promise) { try { return [ 'state' => PromiseInterface::FULFILLED, - 'value' => $promise->wait(), + 'value' => $promise->wait() ]; } catch (RejectionException $e) { return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()]; } catch (\Throwable $e) { return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; + } catch (\Exception $e) { + return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; } } @@ -92,8 +100,10 @@ final class Utils * @see inspect for the inspection state array format. * * @param PromiseInterface[] $promises Traversable of promises to wait upon. + * + * @return array */ - public static function inspectAll($promises): array + public static function inspectAll($promises) { $results = []; foreach ($promises as $key => $promise) { @@ -112,9 +122,12 @@ final class Utils * * @param iterable $promises Iterable of PromiseInterface objects to wait on. * - * @throws \Throwable on error + * @return array + * + * @throws \Exception on error + * @throws \Throwable on error in PHP >=7 */ - public static function unwrap($promises): array + public static function unwrap($promises) { $results = []; foreach ($promises as $key => $promise) { @@ -134,21 +147,22 @@ final class Utils * * @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 */ - public static function all($promises, bool $recursive = false): PromiseInterface + public static function all($promises, $recursive = false) { $results = []; $promise = Each::of( $promises, - function ($value, $idx) use (&$results): void { + function ($value, $idx) use (&$results) { $results[$idx] = $value; }, - function ($reason, $idx, Promise $aggregate): void { + function ($reason, $idx, Promise $aggregate) { $aggregate->reject($reason); } )->then(function () use (&$results) { ksort($results); - return $results; }); @@ -159,7 +173,6 @@ final class Utils return self::all($promises, $recursive); } } - return $results; }); } @@ -180,15 +193,17 @@ final class Utils * * @param int $count Total number of promises. * @param mixed $promises Promises or values. + * + * @return PromiseInterface */ - public static function some(int $count, $promises): PromiseInterface + public static function some($count, $promises) { $results = []; $rejections = []; return Each::of( $promises, - function ($value, $idx, PromiseInterface $p) use (&$results, $count): void { + function ($value, $idx, PromiseInterface $p) use (&$results, $count) { if (Is::settled($p)) { return; } @@ -197,7 +212,7 @@ final class Utils $p->resolve(null); } }, - function ($reason) use (&$rejections): void { + function ($reason) use (&$rejections) { $rejections[] = $reason; } )->then( @@ -209,7 +224,6 @@ final class Utils ); } ksort($results); - return array_values($results); } ); @@ -220,8 +234,10 @@ final class Utils * fulfillment value is not an array of 1 but the value directly. * * @param mixed $promises Promises or values. + * + * @return PromiseInterface */ - public static function any($promises): PromiseInterface + public static function any($promises) { return self::some(1, $promises)->then(function ($values) { return $values[0]; @@ -237,22 +253,23 @@ final class Utils * @see inspect for the inspection state array format. * * @param mixed $promises Promises or values. + * + * @return PromiseInterface */ - public static function settle($promises): PromiseInterface + public static function settle($promises) { $results = []; return Each::of( $promises, - function ($value, $idx) use (&$results): void { + function ($value, $idx) use (&$results) { $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value]; }, - function ($reason, $idx) use (&$results): void { + function ($reason, $idx) use (&$results) { $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason]; } )->then(function () use (&$results) { ksort($results); - return $results; }); } diff --git a/vendor/guzzlehttp/promises/src/functions.php b/vendor/guzzlehttp/promises/src/functions.php new file mode 100644 index 000000000..c03d39d02 --- /dev/null +++ b/vendor/guzzlehttp/promises/src/functions.php @@ -0,0 +1,363 @@ + + * while ($eventLoop->isRunning()) { + * GuzzleHttp\Promise\queue()->run(); + * } + * + * + * @param TaskQueueInterface $assign Optionally specify a new queue instance. + * + * @return TaskQueueInterface + * + * @deprecated queue will be removed in guzzlehttp/promises:2.0. Use Utils::queue instead. + */ +function queue(TaskQueueInterface $assign = null) +{ + return Utils::queue($assign); +} + +/** + * Adds a function to run in the task queue when it is next `run()` and returns + * a promise that is fulfilled or rejected with the result. + * + * @param callable $task Task function to run. + * + * @return PromiseInterface + * + * @deprecated task will be removed in guzzlehttp/promises:2.0. Use Utils::task instead. + */ +function task(callable $task) +{ + return Utils::task($task); +} + +/** + * Creates a promise for a value if the value is not a promise. + * + * @param mixed $value Promise or value. + * + * @return PromiseInterface + * + * @deprecated promise_for will be removed in guzzlehttp/promises:2.0. Use Create::promiseFor instead. + */ +function promise_for($value) +{ + return Create::promiseFor($value); +} + +/** + * Creates a rejected promise for a reason if the reason is not a promise. If + * the provided reason is a promise, then it is returned as-is. + * + * @param mixed $reason Promise or reason. + * + * @return PromiseInterface + * + * @deprecated rejection_for will be removed in guzzlehttp/promises:2.0. Use Create::rejectionFor instead. + */ +function rejection_for($reason) +{ + return Create::rejectionFor($reason); +} + +/** + * Create an exception for a rejected promise value. + * + * @param mixed $reason + * + * @return \Exception|\Throwable + * + * @deprecated exception_for will be removed in guzzlehttp/promises:2.0. Use Create::exceptionFor instead. + */ +function exception_for($reason) +{ + return Create::exceptionFor($reason); +} + +/** + * Returns an iterator for the given value. + * + * @param mixed $value + * + * @return \Iterator + * + * @deprecated iter_for will be removed in guzzlehttp/promises:2.0. Use Create::iterFor instead. + */ +function iter_for($value) +{ + return Create::iterFor($value); +} + +/** + * Synchronously waits on a promise to resolve and returns an inspection state + * array. + * + * Returns a state associative array containing a "state" key mapping to a + * valid promise state. If the state of the promise is "fulfilled", the array + * will contain a "value" key mapping to the fulfilled value of the promise. If + * the promise is rejected, the array will contain a "reason" key mapping to + * the rejection reason of the promise. + * + * @param PromiseInterface $promise Promise or value. + * + * @return array + * + * @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspect instead. + */ +function inspect(PromiseInterface $promise) +{ + return Utils::inspect($promise); +} + +/** + * Waits on all of the provided promises, but does not unwrap rejected promises + * as thrown exception. + * + * Returns an array of inspection state arrays. + * + * @see inspect for the inspection state array format. + * + * @param PromiseInterface[] $promises Traversable of promises to wait upon. + * + * @return array + * + * @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspectAll instead. + */ +function inspect_all($promises) +{ + return Utils::inspectAll($promises); +} + +/** + * Waits on all of the provided promises and returns the fulfilled values. + * + * Returns an array that contains the value of each promise (in the same order + * the promises were provided). An exception is thrown if any of the promises + * are rejected. + * + * @param iterable $promises Iterable of PromiseInterface objects to wait on. + * + * @return array + * + * @throws \Exception on error + * @throws \Throwable on error in PHP >=7 + * + * @deprecated unwrap will be removed in guzzlehttp/promises:2.0. Use Utils::unwrap instead. + */ +function unwrap($promises) +{ + return Utils::unwrap($promises); +} + +/** + * Given an array of promises, return a promise that is fulfilled when all the + * items in the array are fulfilled. + * + * The promise's fulfillment value is an array with fulfillment values at + * respective positions to the original array. If any promise in the array + * 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 + * + * @deprecated all will be removed in guzzlehttp/promises:2.0. Use Utils::all instead. + */ +function all($promises, $recursive = false) +{ + return Utils::all($promises, $recursive); +} + +/** + * Initiate a competitive race between multiple promises or values (values will + * become immediately fulfilled promises). + * + * When count amount of promises have been fulfilled, the returned promise is + * fulfilled with an array that contains the fulfillment values of the winners + * in order of resolution. + * + * This promise is rejected with a {@see AggregateException} if the number of + * fulfilled promises is less than the desired $count. + * + * @param int $count Total number of promises. + * @param mixed $promises Promises or values. + * + * @return PromiseInterface + * + * @deprecated some will be removed in guzzlehttp/promises:2.0. Use Utils::some instead. + */ +function some($count, $promises) +{ + return Utils::some($count, $promises); +} + +/** + * Like some(), with 1 as count. However, if the promise fulfills, the + * fulfillment value is not an array of 1 but the value directly. + * + * @param mixed $promises Promises or values. + * + * @return PromiseInterface + * + * @deprecated any will be removed in guzzlehttp/promises:2.0. Use Utils::any instead. + */ +function any($promises) +{ + return Utils::any($promises); +} + +/** + * Returns a promise that is fulfilled when all of the provided promises have + * been fulfilled or rejected. + * + * The returned promise is fulfilled with an array of inspection state arrays. + * + * @see inspect for the inspection state array format. + * + * @param mixed $promises Promises or values. + * + * @return PromiseInterface + * + * @deprecated settle will be removed in guzzlehttp/promises:2.0. Use Utils::settle instead. + */ +function settle($promises) +{ + return Utils::settle($promises); +} + +/** + * Given an iterator that yields promises or values, returns a promise that is + * fulfilled with a null value when the iterator has been consumed or the + * aggregate promise has been fulfilled or rejected. + * + * $onFulfilled is a function that accepts the fulfilled value, iterator index, + * and the aggregate promise. The callback can invoke any necessary side + * effects and choose to resolve or reject the aggregate if needed. + * + * $onRejected is a function that accepts the rejection reason, iterator index, + * and the aggregate promise. The callback can invoke any necessary side + * effects and choose to resolve or reject the aggregate if needed. + * + * @param mixed $iterable Iterator or array to iterate over. + * @param callable $onFulfilled + * @param callable $onRejected + * + * @return PromiseInterface + * + * @deprecated each will be removed in guzzlehttp/promises:2.0. Use Each::of instead. + */ +function each( + $iterable, + callable $onFulfilled = null, + callable $onRejected = null +) { + return Each::of($iterable, $onFulfilled, $onRejected); +} + +/** + * Like each, but only allows a certain number of outstanding promises at any + * given time. + * + * $concurrency may be an integer or a function that accepts the number of + * pending promises and returns a numeric concurrency limit value to allow for + * dynamic a concurrency size. + * + * @param mixed $iterable + * @param int|callable $concurrency + * @param callable $onFulfilled + * @param callable $onRejected + * + * @return PromiseInterface + * + * @deprecated each_limit will be removed in guzzlehttp/promises:2.0. Use Each::ofLimit instead. + */ +function each_limit( + $iterable, + $concurrency, + callable $onFulfilled = null, + callable $onRejected = null +) { + return Each::ofLimit($iterable, $concurrency, $onFulfilled, $onRejected); +} + +/** + * Like each_limit, but ensures that no promise in the given $iterable argument + * is rejected. If any promise is rejected, then the aggregate promise is + * rejected with the encountered rejection. + * + * @param mixed $iterable + * @param int|callable $concurrency + * @param callable $onFulfilled + * + * @return PromiseInterface + * + * @deprecated each_limit_all will be removed in guzzlehttp/promises:2.0. Use Each::ofLimitAll instead. + */ +function each_limit_all( + $iterable, + $concurrency, + callable $onFulfilled = null +) { + return Each::ofLimitAll($iterable, $concurrency, $onFulfilled); +} + +/** + * Returns true if a promise is fulfilled. + * + * @return bool + * + * @deprecated is_fulfilled will be removed in guzzlehttp/promises:2.0. Use Is::fulfilled instead. + */ +function is_fulfilled(PromiseInterface $promise) +{ + return Is::fulfilled($promise); +} + +/** + * Returns true if a promise is rejected. + * + * @return bool + * + * @deprecated is_rejected will be removed in guzzlehttp/promises:2.0. Use Is::rejected instead. + */ +function is_rejected(PromiseInterface $promise) +{ + return Is::rejected($promise); +} + +/** + * Returns true if a promise is fulfilled or rejected. + * + * @return bool + * + * @deprecated is_settled will be removed in guzzlehttp/promises:2.0. Use Is::settled instead. + */ +function is_settled(PromiseInterface $promise) +{ + return Is::settled($promise); +} + +/** + * Create a new coroutine. + * + * @see Coroutine + * + * @return PromiseInterface + * + * @deprecated coroutine will be removed in guzzlehttp/promises:2.0. Use Coroutine::of instead. + */ +function coroutine(callable $generatorFn) +{ + return Coroutine::of($generatorFn); +} diff --git a/vendor/guzzlehttp/promises/src/functions_include.php b/vendor/guzzlehttp/promises/src/functions_include.php new file mode 100644 index 000000000..34cd1710a --- /dev/null +++ b/vendor/guzzlehttp/promises/src/functions_include.php @@ -0,0 +1,6 @@ +setRules([ '@PER' => true, '@PER:risky' => true, - '@PHP82Migration' => true, + '@PHP81Migration' => true, '@PHPUnit84Migration:risky' => true, 'array_syntax' => ['syntax' => 'short'], 'class_attributes_separation' => true, @@ -68,4 +68,4 @@ return $config->setRules([ ], ]) ->setFinder($finder) - ->setRiskyAllowed(true); + ->setRiskyAllowed(true); \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/.tool-versions b/vendor/maennchen/zipstream-php/.tool-versions index 261817810..54f6ff0b4 100644 --- a/vendor/maennchen/zipstream-php/.tool-versions +++ b/vendor/maennchen/zipstream-php/.tool-versions @@ -1 +1 @@ -php 8.2.5 +php 8.2.0 diff --git a/vendor/maennchen/zipstream-php/README.md b/vendor/maennchen/zipstream-php/README.md index 8ebb2c3cf..155a26582 100644 --- a/vendor/maennchen/zipstream-php/README.md +++ b/vendor/maennchen/zipstream-php/README.md @@ -14,17 +14,13 @@ version. ## Overview -A fast and simple streaming zip file downloader for PHP. Using this library will -save you from having to write the Zip to disk. You can directly send it to the -user, which is much faster. It can work with S3 buckets or any PSR7 Stream. +A fast and simple streaming zip file downloader for PHP. Using this library will save you from having to write the Zip to disk. You can directly send it to the user, which is much faster. It can work with S3 buckets or any PSR7 Stream. Please see the [LICENSE](LICENSE) file for licensing and warranty information. ## Installation -Simply add a dependency on maennchen/zipstream-php to your project's -`composer.json` file if you use Composer to manage the dependencies of your -project. Use following command to add the package to your project's dependencies: +Simply add a dependency on maennchen/zipstream-php to your project's composer.json file if you use Composer to manage the dependencies of your project. Use following command to add the package to your project's dependencies: ```bash composer require maennchen/zipstream-php @@ -33,116 +29,51 @@ composer require maennchen/zipstream-php ## Usage For detailed instructions, please check the -[Documentation](https://maennchen.github.io/ZipStream-PHP/). +[Documentation](https://maennchen.dev/ZipStream-PHP/). + +Here's a simple example: ```php // Autoload the dependencies require 'vendor/autoload.php'; -// create a new zipstream object -$zip = new ZipStream\ZipStream( - outputName: 'example.zip', +// enable output of HTTP headers +$options = new ZipStream\Option\Archive(); +$options->setSendHttpHeaders(true); - // enable output of HTTP headers - sendHttpHeaders: true, -); +// create a new zipstream object +$zip = new ZipStream\ZipStream('example.zip', $options); // create a file named 'hello.txt' -$zip->addFile( - fileName: 'hello.txt', - data: 'This is the contents of hello.txt', -); +$zip->addFile('hello.txt', 'This is the contents of hello.txt'); // add a file named 'some_image.jpg' from a local file 'path/to/image.jpg' -$zip->addFileFromPath( - fileName: 'some_image.jpg', - path: 'path/to/image.jpg', -); +$zip->addFileFromPath('some_image.jpg', 'path/to/image.jpg'); // finish the zip stream $zip->finish(); ``` -## Upgrade to version 3.0.0 - -### General - -- Minimum PHP Version: `8.1` -- Only 64bit Architecture is supported. -- The class `ZipStream\Option\Method` has been replaced with the enum - `ZipStream\CompressionMethod`. -- Most clases have been flagged as `@internal` and should not be used from the - outside. - If you're using internal resources to extend this library, please open an - issue so that a clean interface can be added & published. - The externally available classes & enums are: - - `ZipStream\CompressionMethod` - - `ZipStream\Exception*` - - `ZipStream\ZipStream` - -### Archive Options - -- The class `ZipStream\Option\Archive` has been replaced in favor of named - arguments in the `ZipStream\ZipStream` constuctor. -- The archive options `largeFileSize` & `largeFileMethod` has been removed. If - you want different `compressionMethods` based on the file size, you'll have to - implement this yourself. -- The archive option `httpHeaderCallback` changed the type from `callable` to - `Closure`. -- The archive option `zeroHeader` has been replaced with the option - `defaultEnableZeroHeader` and can be overridden for every file. Its default - value changed from `false` to `true`. -- The archive option `statFiles` was removed since the library no longer checks - filesizes this way. -- The archive option `deflateLevel` has been replaced with the option - `defaultDeflateLevel` and can be overridden for every file. -- The first argument (`name`) of the `ZipStream\ZipStream` constuctor has been - replaced with the named argument `outputName`. -- Headers are now also sent if the `outputName` is empty. If you do not want to - automatically send http headers, set `sendHttpHeaders` to `false`. - -### File Options - -- The class `ZipStream\Option\File` has been replaced in favor of named - arguments in the `ZipStream\ZipStream->addFile*` functions. -- The file option `method` has been renamed to `compressionMethod`. -- The file option `time` has been renamed to `lastModificationDateTime`. -- The file option `size` has been renamed to `maxSize`. - ## Upgrade to version 2.0.0 -https://github.com/maennchen/ZipStream-PHP/tree/2.0.0#upgrade-to-version-200 +- Only the self opened streams will be closed (#139) + If you were relying on ZipStream to close streams that the library didn't open, + you'll need to close them yourself now. ## Upgrade to version 1.0.0 -https://github.com/maennchen/ZipStream-PHP/tree/2.0.0#upgrade-to-version-100 +- All options parameters to all function have been moved from an `array` to structured option objects. See [the wiki](https://github.com/maennchen/ZipStream-PHP/wiki/Available-options) for examples. +- The whole library has been refactored. The minimal PHP requirement has been raised to PHP 7.1. + +## Usage with Symfony and S3 + +You can find example code on [the wiki](https://github.com/maennchen/ZipStream-PHP/wiki/Symfony-example). ## Contributing ZipStream-PHP is a collaborative project. Please take a look at the [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) file. -## Version Support - -Versions are supported according to the table below. - -Please do not open any pull requests contradicting the current version support -status. - -Careful: Always check the `README` on `main` for up-to-date information. - -| Version | New Features | Bugfixes | Security | -|---------|--------------|----------|----------| -| *3* | ✓ | ✓ | ✓ | -| *2* | ✗ | ✓ | ✓ | -| *1* | ✗ | ✗ | ✓ | -| *0* | ✗ | ✗ | ✗ | - -This library aligns itself with the PHP core support. New features and bugfixes -will only target PHP versions according to their current status. - -See: https://www.php.net/supported-versions.php - ## About the Authors - Paul Duncan - https://pablotron.org/ diff --git a/vendor/maennchen/zipstream-php/composer.json b/vendor/maennchen/zipstream-php/composer.json index 98c536a43..2746da19f 100644 --- a/vendor/maennchen/zipstream-php/composer.json +++ b/vendor/maennchen/zipstream-php/composer.json @@ -22,35 +22,26 @@ } ], "require": { - "php-64bit": "^8.1", + "php": "^8.0", "ext-mbstring": "*", - "ext-zlib": "*" + "psr/http-message": "^1.0", + "myclabs/php-enum": "^1.5" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "guzzlehttp/guzzle": "^7.5", + "phpunit/phpunit": "^8.5.8 || ^9.4.2", + "guzzlehttp/guzzle": "^6.5.3 || ^7.2.0", "ext-zip": "*", "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.5", - "friendsofphp/php-cs-fixer": "^3.16", - "vimeo/psalm": "^5.0" - }, - "suggest": { - "psr/http-message": "^2.0", - "guzzlehttp/psr7": "^2.4" + "vimeo/psalm": "^5.0", + "php-coveralls/php-coveralls": "^2.4", + "friendsofphp/php-cs-fixer": "^3.9" }, "scripts": { - "format": "php-cs-fixer fix", - "test": [ - "@test:unit", - "@test:formatted", - "@test:lint" - ], + "format": "PHP_CS_FIXER_IGNORE_ENV=true php-cs-fixer fix", + "test": "composer run test:unit && composer run test:formatted && composer run test:lint", "test:unit": "phpunit --coverage-clover=coverage.clover.xml --coverage-html cov", - "test:unit:slow": "@test:unit --group slow", - "test:unit:fast": "@test:unit --exclude-group slow", - "test:formatted": "@format --dry-run --stop-on-violation --using-cache=no", - "test:lint": "psalm --stats --show-info=true --find-unused-psalm-suppress", + "test:formatted": "composer run format -- --dry-run --stop-on-violation --using-cache=no", + "test:lint": "psalm --stats --show-info --find-unused-psalm-suppress", "coverage:report": "php-coveralls --coverage_clover=coverage.clover.xml --json_path=coveralls-upload.json --insecure", "install:tools": "phive install --trust-gpg-keys 0x67F861C3D889C656", "docs:generate": "tools/phpdocumentor --sourcecode" @@ -60,9 +51,6 @@ "ZipStream\\": "src/" } }, - "autoload-dev": { - "psr-4": { "ZipStream\\Test\\": "test/" } - }, "archive": { "exclude": [ "/composer.lock", diff --git a/vendor/maennchen/zipstream-php/guides/ContentLength.rst b/vendor/maennchen/zipstream-php/guides/ContentLength.rst index 21fea34d7..e51e69276 100644 --- a/vendor/maennchen/zipstream-php/guides/ContentLength.rst +++ b/vendor/maennchen/zipstream-php/guides/ContentLength.rst @@ -1,47 +1,79 @@ Adding Content-Length header ============= -Adding a ``Content-Length`` header for ``ZipStream`` can be achieved by -using the options ``SIMULATION_STRICT`` or ``SIMULATION_LAX`` in the -``operationMode`` parameter. +Adding a ``Content-Length`` header for ``ZipStream`` is not trivial since the +size is not known beforehand. -In the ``SIMULATION_STRICT`` mode, ``ZipStream`` will not allow to calculate the -size based on reading the whole file. ``SIMULATION_LAX`` will read the whole -file if neccessary. - -``SIMULATION_STRICT`` is therefore useful to make sure that the size can be -calculated efficiently. +The following workaround adds an approximated header: .. code-block:: php - use ZipStream\OperationMode; - use ZipStream\ZipStream; - $zip = new ZipStream( - operationMode: OperationMode::SIMULATE_STRICT, // or SIMULATE_LAX - defaultEnableZeroHeader: false, - sendHttpHeaders: true, - outputStream: $stream, - ); + class Zip + { + /** @var string */ + private $name; - // Normally add files - $zip->addFile('sample.txt', 'Sample String Data'); + private $files = []; - // Use addFileFromCallback and exactSize if you want to defer opening of - // the file resource - $zip->addFileFromCallback( - 'sample.txt', - exactSize: 18, - callback: function () { - return fopen('...'); + public function __construct($name) + { + $this->name = $name; } - ); - // Read resulting file size - $size = $zip->finish(); - - // Tell it to the browser - header('Content-Length: '. $size); - - // Execute the Simulation and stream the actual zip to the client - $zip->executeSimulation(); + public function addFile($name, $data) + { + $this->files[] = ['type' => 'addFile', 'name' => $name, 'data' => $data]; + } + public function addFileFromPath($name, $path) + { + $this->files[] = ['type' => 'addFileFromPath', 'name' => $name, 'path' => $path]; + } + + public function getEstimate() + { + $estimate = 22; + foreach ($this->files as $file) { + $estimate += 76 + 2 * strlen($file['name']); + if ($file['type'] === 'addFile') { + $estimate += strlen($file['data']); + } + if ($file['type'] === 'addFileFromPath') { + $estimate += filesize($file['path']); + } + } + return $estimate; + } + + public function finish() + { + header('Content-Length: ' . $this->getEstimate()); + $options = new \ZipStream\Option\Archive(); + $options->setSendHttpHeaders(true); + $options->setEnableZip64(false); + $options->setDeflateLevel(-1); + $zip = new \ZipStream\ZipStream($this->name, $options); + + $fileOptions = new \ZipStream\Option\File(); + $fileOptions->setMethod(\ZipStream\Option\Method::STORE()); + foreach ($this->files as $file) { + if ($file['type'] === 'addFile') { + $zip->addFile($file['name'], $file['data'], $fileOptions); + } + if ($file['type'] === 'addFileFromPath') { + $zip->addFileFromPath($file['name'], $file['path'], $fileOptions); + } + } + $zip->finish(); + exit; + } + } + +It only works with the following constraints: + +- All file content is known beforehand. +- Content Deflation is disabled + +Thanks to +`partiellkorrekt `_ +for this workaround. \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/guides/FlySystem.rst b/vendor/maennchen/zipstream-php/guides/FlySystem.rst index 4e6c6fb82..0243f2482 100644 --- a/vendor/maennchen/zipstream-php/guides/FlySystem.rst +++ b/vendor/maennchen/zipstream-php/guides/FlySystem.rst @@ -14,21 +14,20 @@ default one, and pass it to Flysystem ``putStream`` method. // the content is lost when closing the stream / opening another one $tempStream = fopen('php://memory', 'w+'); + // Init Options + $zipStreamOptions = new Archive(); + $zipStreamOptions->setOutputStream($tempStream); + // Create Zip Archive - $zipStream = new ZipStream( - outputStream: $tempStream, - outputName: 'test.zip', - ); + $zipStream = new ZipStream('test.zip', $zipStreamOptions); $zipStream->addFile('test.txt', 'text'); $zipStream->finish(); - // Store File - // (see Flysystem documentation, and all its framework integration) - // Can be any adapter (AWS, Google, Ftp, etc.) - $adapter = new Local(__DIR__.'/path/to/folder'); + // Store File (see Flysystem documentation, and all its framework integration) + $adapter = new Local(__DIR__.'/path/to/folder'); // Can be any adapter (AWS, Google, Ftp, etc.) $filesystem = new Filesystem($adapter); - $filesystem->writeStream('test.zip', $tempStream) + $filesystem->putStream('test.zip', $tempStream) // Close Stream - fclose($tempStream); + fclose($tempStream); \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/guides/Options.rst b/vendor/maennchen/zipstream-php/guides/Options.rst index 5e92e94d6..eabaa6f34 100644 --- a/vendor/maennchen/zipstream-php/guides/Options.rst +++ b/vendor/maennchen/zipstream-php/guides/Options.rst @@ -2,65 +2,60 @@ Available options =============== Here is the full list of options available to you. You can also have a look at -``src/ZipStream.php`` file. +``src/Option/Archive.php`` file. + +First, an instance of ``ZipStream\Option\Archive`` needs to be created, and +after that you use setters methods to modify the values. .. code-block:: php - use ZipStream\ZipStream; + use ZipStream\Option\Archive as ArchiveOptions; require_once 'vendor/autoload.php'; - $zip = new ZipStream( - // Define output stream - // (argument is eiter a resource or implementing - // `Psr\Http\Message\StreamInterface`) - // - // Setup with `psr/http-message` & `guzzlehttp/psr7` dependencies - // required when using `Psr\Http\Message\StreamInterface`. - outputStream: $filePointer, + $opt = new ArchiveOptions(); - // Set the deflate level (default is 6; use -1 to disable it) - defaultDeflateLevel: 6, + // Define output stream (argument is of type resource) + $opt->setOutputStream($fd); - // Add a comment to the zip file - comment: 'This is a comment.', + // Set the deflate level (default is 6; use -1 to disable it) + $opt->setDeflateLevel(6); - // Send http headers (default is true) - sendHttpHeaders: false, + // Add a comment to the zip file + $opt->setComment('This is a comment.'); - // HTTP Content-Disposition. - // Defaults to 'attachment', where FILENAME is the specified filename. - // Note that this does nothing if you are not sending HTTP headers. - contentDisposition: 'attachment', + // Size, in bytes, of the largest file to try and load into memory (used by addFileFromPath()). Large files may also be compressed differently; see the 'largeFileMethod' option. + $opt->setLargeFileSize(30000000); - // Output Name for HTTP Content-Disposition - // Defaults to no name - outputName: "example.zip", + // How to handle large files. Legal values are STORE (the default), or DEFLATE. Store sends the file raw and is significantly faster, while DEFLATE compresses the file and is much, much slower. Note that deflate must compress the file twice and is extremely slow. + $opt->setLargeFileMethod(ZipStream\Option\Method::STORE()); + $opt->setLargeFileMethod(ZipStream\Option\Method::DEFLATE()); - // HTTP Content-Type. - // Defaults to 'application/x-zip'. - // Note that this does nothing if you are not sending HTTP headers. - contentType: 'application/x-zip', + // Send http headers (default is false) + $opt->setSendHttpHeaders(false); - // Set the function called for setting headers. - // Default is the `header()` of PHP - httpHeaderCallback: header(...), + // HTTP Content-Disposition. Defaults to 'attachment', where FILENAME is the specified filename. Note that this does nothing if you are not sending HTTP headers. + $opt->setContentDisposition('attachment'); - // Enable streaming files with single read where general purpose bit 3 - // indicates local file header contain zero values in crc and size - // fields, these appear only after file contents in data descriptor - // block. - // Set to true if your input stream is remote - // (used with addFileFromStream()). - // Default is false. - defaultEnableZeroHeader: false, + // Set the content type (does nothing if you are not sending HTTP headers) + $opt->setContentType('application/x-zip'); - // Enable zip64 extension, allowing very large archives - // (> 4Gb or file count > 64k) - // Default is true - enableZip64: true, + // Set the function called for setting headers. Default is the `header()` of PHP + $opt->setHttpHeaderCallback('header'); - // Flush output buffer after every write - // Default is false - flushOutput: true, - ); + // Enable streaming files with single read where general purpose bit 3 indicates local file header contain zero values in crc and size fields, these appear only after file contents in data descriptor block. Default is false. Set to true if your input stream is remote (used with addFileFromStream()). + $opt->setZeroHeader(false); + + // Enable reading file stat for determining file size. When a 32-bit system reads file size that is over 2 GB, invalid value appears in file size due to integer overflow. Should be disabled on 32-bit systems with method addFileFromPath if any file may exceed 2 GB. In this case file will be read in blocks and correct size will be determined from content. Default is true. + $opt->setStatFiles(true); + + // Enable zip64 extension, allowing very large archives (> 4Gb or file count > 64k) + // default is true + $opt->setEnableZip64(true); + + // Flush output buffer after every write + // default is false + $opt->setFlushOutput(true); + + // Now that everything is set you can pass the options to the ZipStream instance + $zip = new ZipStream('example.zip', $opt); diff --git a/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst b/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst index 22af71d4a..4b4ca4b34 100644 --- a/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst +++ b/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst @@ -12,10 +12,7 @@ Example --------------- .. code-block:: php - + $stream = $response->getBody(); // add a file named 'streamfile.txt' from the content of the stream - $zip->addFileFromPsr7Stream( - fileName: 'streamfile.txt', - stream: $stream, - ); + $zip->addFileFromPsr7Stream('streamfile.txt', $stream); diff --git a/vendor/maennchen/zipstream-php/guides/StreamOutput.rst b/vendor/maennchen/zipstream-php/guides/StreamOutput.rst index 9f3165b75..1a0495fae 100644 --- a/vendor/maennchen/zipstream-php/guides/StreamOutput.rst +++ b/vendor/maennchen/zipstream-php/guides/StreamOutput.rst @@ -5,9 +5,9 @@ Stream to S3 Bucket --------------- .. code-block:: php - use Aws\S3\S3Client; use Aws\Credentials\CredentialProvider; + use ZipStream\Option\Archive; use ZipStream\ZipStream; $bucket = 'your bucket name'; @@ -21,19 +21,13 @@ Stream to S3 Bucket $zipFile = fopen("s3://$bucket/example.zip", 'w'); - $zip = new ZipStream( - enableZip64: false, - outputStream: $zipFile, - ); + $options = new Archive(); + $options->setEnableZip64(false); + $options->setOutputStream($zipFile); - $zip->addFile( - fileName: 'file1.txt', - data: 'File1 data', - ); - $zip->addFile( - fileName: 'file2.txt', - data: 'File2 data', - ); + $zip = new ZipStream(null, $options); + $zip->addFile('file1.txt', 'File1 data'); + $zip->addFile('file2.txt', 'File2 data'); $zip->finish(); - fclose($zipFile); + fclose($zipFile); \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/guides/Symfony.rst b/vendor/maennchen/zipstream-php/guides/Symfony.rst index 902552c92..18f905958 100644 --- a/vendor/maennchen/zipstream-php/guides/Symfony.rst +++ b/vendor/maennchen/zipstream-php/guides/Symfony.rst @@ -31,7 +31,7 @@ stored in an AWS S3 bucket by key: */ public function zipStreamAction() { - // sample test file on s3 + //sample test file on s3 $s3keys = array( "ziptestfolder/file1.txt" ); @@ -39,18 +39,18 @@ stored in an AWS S3 bucket by key: $s3Client = $this->get('app.amazon.s3'); //s3client service $s3Client->registerStreamWrapper(); //required - // using StreamedResponse to wrap ZipStream functionality - // for files on AWS s3. + //using StreamedResponse to wrap ZipStream functionality for files on AWS s3. $response = new StreamedResponse(function() use($s3keys, $s3Client) { // Define suitable options for ZipStream Archive. + $options = new \ZipStream\Option\Archive(); + $options->setContentType('application/octet-stream'); // this is needed to prevent issues with truncated zip files + $options->setZeroHeader(true); + $options->setComment('test zip file.'); + //initialise zipstream with output zip filename and options. - $zip = new ZipStream\ZipStream( - outputName: 'test.zip', - defaultEnableZeroHeader: true, - contentType: 'application/octet-stream', - ); + $zip = new ZipStream\ZipStream('test.zip', $options); //loop keys - useful for multiple files foreach ($s3keys as $key) { @@ -58,19 +58,15 @@ stored in an AWS S3 bucket by key: //file using the same name. $fileName = basename($key); - // concatenate s3path. - // replace with your bucket name or get from parameters file. - $bucket = 'bucketname'; + //concatenate s3path. + $bucket = 'bucketname'; //replace with your bucket name or get from parameters file. $s3path = "s3://" . $bucket . "/" . $key; //addFileFromStream if ($streamRead = fopen($s3path, 'r')) { - $zip->addFileFromStream( - fileName: $fileName, - stream: $streamRead, - ); + $zip->addFileFromStream($fileName, $streamRead); } else { - die('Could not open stream for reading'); + die('Could not open stream for reading'); } } @@ -127,4 +123,4 @@ You need to add correct permissions 's3' => ['ACL' => 'public-read'], ]); - fopen($path, 'w', null, $outputContext); + fopen($path, 'w', null, $outputContext); \ No newline at end of file diff --git a/vendor/maennchen/zipstream-php/guides/index.rst b/vendor/maennchen/zipstream-php/guides/index.rst index 4583ca58e..67f504b25 100644 --- a/vendor/maennchen/zipstream-php/guides/index.rst +++ b/vendor/maennchen/zipstream-php/guides/index.rst @@ -22,20 +22,11 @@ Installation Simply add a dependency on ``maennchen/zipstream-php`` to your project's ``composer.json`` file if you use Composer to manage the dependencies of your -project. Use following command to add the package to your project's -dependencies: +project. Use following command to add the package to your project's dependencies: .. code-block:: sh composer require maennchen/zipstream-php -If you want to use``addFileFromPsr7Stream``` -(``Psr\Http\Message\StreamInterface``) or use a stream instead of a -``resource`` as ``outputStream``, the following dependencies must be installed -as well: - -.. code-block:: sh - composer require psr/http-message guzzlehttp/psr7 - If ``composer install`` yields the following error, your installation is missing the `mbstring extension `_, either `install it `_ @@ -61,42 +52,25 @@ Here's a simple example: // Autoload the dependencies require 'vendor/autoload.php'; - // create a new zipstream object - $zip = new ZipStream\ZipStream( - outputName: 'example.zip', + // enable output of HTTP headers + $options = new ZipStream\Option\Archive(); + $options->setSendHttpHeaders(true); - // enable output of HTTP headers - sendHttpHeaders: true, - ); + // create a new zipstream object + $zip = new ZipStream\ZipStream('example.zip', $options); // create a file named 'hello.txt' - $zip->addFile( - fileName: 'hello.txt', - data: 'This is the contents of hello.txt', - ); + $zip->addFile('hello.txt', 'This is the contents of hello.txt'); // add a file named 'some_image.jpg' from a local file 'path/to/image.jpg' - $zip->addFileFromPath( - fileName: 'some_image.jpg', - path: 'path/to/image.jpg', - ); + $zip->addFileFromPath('some_image.jpg', 'path/to/image.jpg'); // add a file named 'goodbye.txt' from an open stream resource - $filePointer = tmpfile(); - fwrite($filePointer, 'The quick brown fox jumped over the lazy dog.'); - rewind($filePointer); - $zip->addFileFromStream( - fileName: 'goodbye.txt', - stream: $filePointer, - ); - fclose($filePointer); - - // add a file named 'streamfile.txt' from the body of a `guzzle` response - // Setup with `psr/http-message` & `guzzlehttp/psr7` dependencies required. - $zip->addFileFromPsr7Stream( - fileName: 'streamfile.txt', - stream: $response->getBody(), - ); + $fp = tmpfile(); + fwrite($fp, 'The quick brown fox jumped over the lazy dog.'); + rewind($fp); + $zip->addFileFromStream('goodbye.txt', $fp); + fclose($fp); // finish the zip stream $zip->finish(); diff --git a/vendor/maennchen/zipstream-php/phpunit.xml.dist b/vendor/maennchen/zipstream-php/phpunit.xml.dist index 1b02a3af8..8a2f3188f 100644 --- a/vendor/maennchen/zipstream-php/phpunit.xml.dist +++ b/vendor/maennchen/zipstream-php/phpunit.xml.dist @@ -1,15 +1,14 @@ - - + + + + src + + test - - - src - - diff --git a/vendor/maennchen/zipstream-php/psalm.xml b/vendor/maennchen/zipstream-php/psalm.xml index 5d050d14a..4e4c4f607 100644 --- a/vendor/maennchen/zipstream-php/psalm.xml +++ b/vendor/maennchen/zipstream-php/psalm.xml @@ -1,12 +1,9 @@ @@ -14,10 +11,43 @@ + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/maennchen/zipstream-php/src/Bigint.php b/vendor/maennchen/zipstream-php/src/Bigint.php new file mode 100644 index 000000000..f2565e980 --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Bigint.php @@ -0,0 +1,174 @@ +fillBytes($value, 0, 8); + } + + /** + * Get an instance + * + * @param int $value + * @return Bigint + */ + public static function init(int $value = 0): self + { + return new self($value); + } + + /** + * Fill bytes from low to high + * + * @param int $low + * @param int $high + * @return Bigint + */ + public static function fromLowHigh(int $low, int $high): self + { + $bigint = new self(); + $bigint->fillBytes($low, 0, 4); + $bigint->fillBytes($high, 4, 4); + return $bigint; + } + + /** + * Get high 32 + * + * @return int + */ + public function getHigh32(): int + { + return $this->getValue(4, 4); + } + + /** + * Get value from bytes array + * + * @param int $end + * @param int $length + * @return int + */ + public function getValue(int $end = 0, int $length = 8): int + { + $result = 0; + for ($i = $end + $length - 1; $i >= $end; $i--) { + $result <<= 8; + $result |= $this->bytes[$i]; + } + return $result; + } + + /** + * Get low FF + * + * @param bool $force + * @return float + */ + public function getLowFF(bool $force = false): float + { + if ($force || $this->isOver32()) { + return (float)0xFFFFFFFF; + } + return (float)$this->getLow32(); + } + + /** + * Check if is over 32 + * + * @psalm-suppress ArgumentTypeCoercion + * @param bool $force + * @return bool + */ + public function isOver32(bool $force = false): bool + { + // value 0xFFFFFFFF already needs a Zip64 header + return $force || + max(array_slice($this->bytes, 4, 4)) > 0 || + min(array_slice($this->bytes, 0, 4)) === 0xFF; + } + + /** + * Get low 32 + * + * @return int + */ + public function getLow32(): int + { + return $this->getValue(0, 4); + } + + /** + * Get hexadecimal + * + * @return string + */ + public function getHex64(): string + { + $result = '0x'; + for ($i = 7; $i >= 0; $i--) { + $result .= sprintf('%02X', $this->bytes[$i]); + } + return $result; + } + + /** + * Add + * + * @param Bigint $other + * @return Bigint + */ + public function add(self $other): self + { + $result = clone $this; + $overflow = false; + for ($i = 0; $i < 8; $i++) { + $result->bytes[$i] += $other->bytes[$i]; + if ($overflow) { + $result->bytes[$i]++; + $overflow = false; + } + if ($result->bytes[$i] & 0x100) { + $overflow = true; + $result->bytes[$i] &= 0xFF; + } + } + if ($overflow) { + throw new OverflowException(); + } + return $result; + } + + /** + * Fill the bytes field with int + * + * @param int $value + * @param int $start + * @param int $count + * @return void + */ + protected function fillBytes(int $value, int $start, int $count): void + { + for ($i = 0; $i < $count; $i++) { + $this->bytes[$start + $i] = $i >= PHP_INT_SIZE ? 0 : $value & 0xFF; + $value >>= 8; + } + } +} diff --git a/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php b/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php deleted file mode 100644 index ffcfc6e97..000000000 --- a/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php +++ /dev/null @@ -1,52 +0,0 @@ -value), - new PackField(format: 'V', value: Time::dateTimeToDosTime($lastModificationDateTime)), - new PackField(format: 'V', value: $crc32), - new PackField(format: 'V', value: $compressedSize), - new PackField(format: 'V', value: $uncompressedSize), - new PackField(format: 'v', value: strlen($fileName)), - new PackField(format: 'v', value: strlen($extraField)), - new PackField(format: 'v', value: strlen($fileComment)), - new PackField(format: 'v', value: $diskNumberStart), - new PackField(format: 'v', value: $internalFileAttributes), - new PackField(format: 'V', value: $externalFileAttributes), - new PackField(format: 'V', value: $relativeOffsetOfLocalHeader), - ) . $fileName . $extraField . $fileComment; - } -} diff --git a/vendor/maennchen/zipstream-php/src/CompressionMethod.php b/vendor/maennchen/zipstream-php/src/CompressionMethod.php deleted file mode 100644 index 51e436370..000000000 --- a/vendor/maennchen/zipstream-php/src/CompressionMethod.php +++ /dev/null @@ -1,106 +0,0 @@ -format(DateTimeInterface::ATOM) . " can't be represented as DOS time / date."); - } -} diff --git a/vendor/maennchen/zipstream-php/src/Exception/EncodingException.php b/vendor/maennchen/zipstream-php/src/Exception/EncodingException.php new file mode 100644 index 000000000..5b0267d2f --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Exception/EncodingException.php @@ -0,0 +1,14 @@ +resource = $resource; - parent::__construct('Function ' . $function . 'failed on resource.'); - } -} diff --git a/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php b/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php deleted file mode 100644 index 717c1aafe..000000000 --- a/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php +++ /dev/null @@ -1,19 +0,0 @@ -fileName = self::filterFilename($fileName); - $this->checkEncoding(); + public $opt; - if ($this->enableZeroHeader) { - $this->generalPurposeBitFlag |= GeneralPurposeBitFlag::ZERO_HEADER; - } + /** + * @var Bigint + */ + public $len; - $this->version = $this->compressionMethod === CompressionMethod::DEFLATE ? Version::DEFLATE : Version::STORE; + /** + * @var Bigint + */ + public $zlen; + + /** @var int */ + public $crc; + + /** + * @var Bigint + */ + public $hlen; + + /** + * @var Bigint + */ + public $ofs; + + /** + * @var int + */ + public $bits; + + /** + * @var Version + */ + public $version; + + /** + * @var ZipStream + */ + public $zip; + + /** + * @var resource + */ + private $deflate; + + /** + * @var HashContext + */ + private $hash; + + /** + * @var Method + */ + private $method; + + /** + * @var Bigint + */ + private $totalLength; + + public function __construct(ZipStream $zip, string $name, ?FileOptions $opt = null) + { + $this->zip = $zip; + + $this->name = $name; + $this->opt = $opt ?: new FileOptions(); + $this->method = $this->opt->getMethod(); + $this->version = Version::STORE(); + $this->ofs = new Bigint(); } - public function cloneSimulationExecution(): self + public function processPath(string $path): void { - return new self( - $this->fileName, - $this->dataCallback, - OperationMode::NORMAL, - $this->startOffset, - $this->compressionMethod, - $this->comment, - $this->lastModificationDateTime, - $this->deflateLevel, - $this->maxSize, - $this->exactSize, - $this->enableZip64, - $this->enableZeroHeader, - $this->send, - $this->recordSentBytes, - ); - } - - public function process(): string - { - $forecastSize = $this->forecastSize(); - - if ($this->enableZeroHeader) { - // No calculation required - } elseif ($this->isSimulation() && $forecastSize) { - $this->uncompressedSize = $forecastSize; - $this->compressedSize = $forecastSize; - } else { - $this->readStream(send: false); - if (rewind($this->unpackStream()) === false) { - throw new ResourceActionException('rewind', $this->unpackStream()); + if (!is_readable($path)) { + if (!file_exists($path)) { + throw new FileNotFoundException($path); } + throw new FileNotReadableException($path); } - - $this->addFileHeader(); - - $detectedSize = $forecastSize ?? $this->compressedSize; - - if ( - $this->isSimulation() && - $detectedSize > 0 - ) { - ($this->recordSentBytes)($detectedSize); + if ($this->zip->isLargeFile($path) === false) { + $data = file_get_contents($path); + $this->processData($data); } else { - $this->readStream(send: true); + $this->method = $this->zip->opt->getLargeFileMethod(); + + $stream = new Stream(fopen($path, 'rb')); + $this->processStream($stream); + $stream->close(); + } + } + + public function processData(string $data): void + { + $this->len = new Bigint(strlen($data)); + $this->crc = crc32($data); + + // compress data if needed + if ($this->method->equals(Method::DEFLATE())) { + $data = gzdeflate($data); } + $this->zlen = new Bigint(strlen($data)); + $this->addFileHeader(); + $this->zip->send($data); $this->addFileFooter(); - return $this->getCdrFile(); - } - - /** - * @return resource - */ - private function unpackStream() - { - if ($this->stream) { - return $this->stream; - } - - if ($this->operationMode === OperationMode::SIMULATE_STRICT) { - throw new SimulationFileUnknownException(); - } - - $this->stream = ($this->dataCallback)(); - - if (!$this->enableZeroHeader && !stream_get_meta_data($this->stream)['seekable']) { - throw new StreamNotSeekableException(); - } - if (!( - str_contains(stream_get_meta_data($this->stream)['mode'], 'r') - || str_contains(stream_get_meta_data($this->stream)['mode'], 'w+') - || str_contains(stream_get_meta_data($this->stream)['mode'], 'a+') - || str_contains(stream_get_meta_data($this->stream)['mode'], 'x+') - || str_contains(stream_get_meta_data($this->stream)['mode'], 'c+') - )) { - throw new StreamNotReadableException(); - } - - return $this->stream; - } - - private function forecastSize(): ?int - { - if ($this->compressionMethod !== CompressionMethod::STORE) { - return null; - } - if ($this->exactSize) { - return $this->exactSize; - } - $fstat = fstat($this->unpackStream()); - if (!$fstat || !array_key_exists('size', $fstat) || $fstat['size'] < 1) { - return null; - } - - if ($this->maxSize !== null && $this->maxSize < $fstat['size']) { - return $this->maxSize; - } - - return $fstat['size']; } /** * Create and send zip header for this file. + * + * @return void + * @throws \ZipStream\Exception\EncodingException */ - private function addFileHeader(): void + public function addFileHeader(): void { - $forceEnableZip64 = $this->enableZeroHeader && $this->enableZip64; + $name = static::filterFilename($this->name); - $footer = $this->buildZip64ExtraBlock($forceEnableZip64); + // calculate name length + $nameLength = strlen($name); - $zip64Enabled = $footer !== ''; + // create dos timestamp + $time = static::dosTime($this->opt->getTime()->getTimestamp()); - if($zip64Enabled) { - $this->version = Version::ZIP64; + $comment = $this->opt->getComment(); + + if (!mb_check_encoding($name, 'ASCII') || + !mb_check_encoding($comment, 'ASCII')) { + // Sets Bit 11: Language encoding flag (EFS). If this bit is set, + // the filename and comment fields for this file + // MUST be encoded using UTF-8. (see APPENDIX D) + if (mb_check_encoding($name, 'UTF-8') && + mb_check_encoding($comment, 'UTF-8')) { + $this->bits |= self::BIT_EFS_UTF8; + } } - if ($this->generalPurposeBitFlag & GeneralPurposeBitFlag::EFS) { - // Put the tricky entry to - // force Linux unzip to lookup EFS flag. - $footer .= Zs\ExtendedInformationExtraField::generate(); + if ($this->method->equals(Method::DEFLATE())) { + $this->version = Version::DEFLATE(); } - $data = LocalFileHeader::generate( - versionNeededToExtract: $this->version->value, - generalPurposeBitFlag: $this->generalPurposeBitFlag, - compressionMethod: $this->compressionMethod, - lastModificationDateTime: $this->lastModificationDateTime, - crc32UncompressedData: $this->crc, - compressedSize: $zip64Enabled - ? 0xFFFFFFFF - : $this->compressedSize, - uncompressedSize: $zip64Enabled - ? 0xFFFFFFFF - : $this->uncompressedSize, - fileName: $this->fileName, - extraField: $footer, - ); + $force = (bool)($this->bits & self::BIT_ZERO_HEADER) && + $this->zip->opt->isEnableZip64(); + $footer = $this->buildZip64ExtraBlock($force); - ($this->send)($data); + // If this file will start over 4GB limit in ZIP file, + // CDR record will have to use Zip64 extension to describe offset + // to keep consistency we use the same value here + if ($this->zip->ofs->isOver32()) { + $this->version = Version::ZIP64(); + } + + $fields = [ + ['V', ZipStream::FILE_HEADER_SIGNATURE], + ['v', $this->version->getValue()], // Version needed to Extract + ['v', $this->bits], // General purpose bit flags - data descriptor flag set + ['v', $this->method->getValue()], // Compression method + ['V', $time], // Timestamp (DOS Format) + ['V', $this->crc], // CRC32 of data (0 -> moved to data descriptor footer) + ['V', $this->zlen->getLowFF($force)], // Length of compressed data (forced to 0xFFFFFFFF for zero header) + ['V', $this->len->getLowFF($force)], // Length of original data (forced to 0xFFFFFFFF for zero header) + ['v', $nameLength], // Length of filename + ['v', strlen($footer)], // Extra data (see above) + ]; + + // pack fields and calculate "total" length + $header = ZipStream::packFields($fields); + + // print header and filename + $data = $header . $name . $footer; + $this->zip->send($data); + + // save header length + $this->hlen = Bigint::init(strlen($data)); } /** * Strip characters that are not legal in Windows filenames * to prevent compatibility issues + * + * @param string $filename Unprocessed filename + * @return string */ - private static function filterFilename( - /** - * Unprocessed filename - */ - string $fileName - ): string { + public static function filterFilename(string $filename): string + { // strip leading slashes from file name // (fixes bug in windows archive viewer) - $fileName = ltrim($fileName, '/'); + $filename = preg_replace('/^\\/+/', '', $filename); - return str_replace(['\\', ':', '*', '?', '"', '<', '>', '|'], '_', $fileName); + return str_replace(['\\', ':', '*', '?', '"', '<', '>', '|'], '_', $filename); } - private function checkEncoding(): void + /** + * Create and send data descriptor footer for this file. + * + * @return void + */ + public function addFileFooter(): void { - // Sets Bit 11: Language encoding flag (EFS). If this bit is set, - // the filename and comment fields for this file - // MUST be encoded using UTF-8. (see APPENDIX D) - if (mb_check_encoding($this->fileName, 'UTF-8') && - mb_check_encoding($this->comment, 'UTF-8')) { - $this->generalPurposeBitFlag |= GeneralPurposeBitFlag::EFS; - } - } + if ($this->bits & self::BIT_ZERO_HEADER) { + // compressed and uncompressed size + $sizeFormat = 'V'; + if ($this->zip->opt->isEnableZip64()) { + $sizeFormat = 'P'; + } + $fields = [ + ['V', ZipStream::DATA_DESCRIPTOR_SIGNATURE], + ['V', $this->crc], // CRC32 + [$sizeFormat, $this->zlen], // Length of compressed data + [$sizeFormat, $this->len], // Length of original data + ]; - private function buildZip64ExtraBlock(bool $force = false): string - { - $outputZip64ExtraBlock = false; - - $originalSize = null; - if ($force || $this->uncompressedSize > 0xFFFFFFFF) { - $outputZip64ExtraBlock = true; - $originalSize = $this->uncompressedSize; - } - - $compressedSize = null; - if ($force || $this->compressedSize > 0xFFFFFFFF) { - $outputZip64ExtraBlock = true; - $compressedSize = $this->compressedSize; - } - - // If this file will start over 4GB limit in ZIP file, - // CDR record will have to use Zip64 extension to describe offset - // to keep consistency we use the same value here - $relativeHeaderOffset = null; - if ($this->startOffset > 0xFFFFFFFF) { - $outputZip64ExtraBlock = true; - $relativeHeaderOffset = $this->startOffset; - } - - if (!$outputZip64ExtraBlock) { - return ''; - } - - if (!$this->enableZip64) { - throw new OverflowException(); - } - - return Zip64\ExtendedInformationExtraField::generate( - originalSize: $originalSize, - compressedSize: $compressedSize, - relativeHeaderOffset: $relativeHeaderOffset, - diskStartNumber: null, - ); - } - - private function addFileFooter(): void - { - if (($this->compressedSize > 0xFFFFFFFF || $this->uncompressedSize > 0xFFFFFFFF) && $this->version !== Version::ZIP64) { - throw new OverflowException(); - } - - if (!$this->enableZeroHeader) { - return; - } - - if ($this->version === Version::ZIP64) { - $footer = Zip64\DataDescriptor::generate( - crc32UncompressedData: $this->crc, - compressedSize: $this->compressedSize, - uncompressedSize: $this->uncompressedSize, - ); + $footer = ZipStream::packFields($fields); + $this->zip->send($footer); } else { - $footer = DataDescriptor::generate( - crc32UncompressedData: $this->crc, - compressedSize: $this->compressedSize, - uncompressedSize: $this->uncompressedSize, - ); + $footer = ''; } - - ($this->send)($footer); + $this->totalLength = $this->hlen->add($this->zlen)->add(Bigint::init(strlen($footer))); + $this->zip->addToCdr($this); } - private function readStream(bool $send): void + public function processStream(StreamInterface $stream): void { - $this->compressedSize = 0; - $this->uncompressedSize = 0; - $hash = hash_init('crc32b'); + $this->zlen = new Bigint(); + $this->len = new Bigint(); - $deflate = $this->compressionInit(); - - while ( - !feof($this->unpackStream()) && - ($this->maxSize === null || $this->uncompressedSize < $this->maxSize) && - ($this->exactSize === null || $this->uncompressedSize < $this->exactSize) - ) { - $readLength = min( - ($this->maxSize ?? PHP_INT_MAX) - $this->uncompressedSize, - ($this->exactSize ?? PHP_INT_MAX) - $this->uncompressedSize, - self::CHUNKED_READ_BLOCK_SIZE - ); - - $data = fread($this->unpackStream(), $readLength); - - hash_update($hash, $data); - - $this->uncompressedSize += strlen($data); - - if ($deflate) { - $data = deflate_add( - $deflate, - $data, - feof($this->unpackStream()) ? ZLIB_FINISH : ZLIB_NO_FLUSH - ); - } - - $this->compressedSize += strlen($data); - - if ($send) { - ($this->send)($data); - } - } - - if ($this->exactSize && $this->uncompressedSize !== $this->exactSize) { - throw new FileSizeIncorrectException(expectedSize: $this->exactSize, actualSize: $this->uncompressedSize); - } - - $this->crc = hexdec(hash_final($hash)); - } - - private function compressionInit(): ?DeflateContext - { - switch($this->compressionMethod) { - case CompressionMethod::STORE: - // Noting to do - return null; - case CompressionMethod::DEFLATE: - $deflateContext = deflate_init( - ZLIB_ENCODING_RAW, - ['level' => $this->deflateLevel] - ); - - if (!$deflateContext) { - // @codeCoverageIgnoreStart - throw new RuntimeException("Can't initialize deflate context."); - // @codeCoverageIgnoreEnd - } - - // False positive, resource is no longer returned from this function - return $deflateContext; - default: - // @codeCoverageIgnoreStart - throw new RuntimeException('Unsupported Compression Method ' . print_r($this->compressionMethod, true)); - // @codeCoverageIgnoreEnd + if ($this->zip->opt->isZeroHeader()) { + $this->processStreamWithZeroHeader($stream); + } else { + $this->processStreamWithComputedHeader($stream); } } - private function getCdrFile(): string + /** + * Send CDR record for specified file. + * + * @return string + */ + public function getCdrFile(): string { + $name = static::filterFilename($this->name); + + // get attributes + $comment = $this->opt->getComment(); + + // get dos timestamp + $time = static::dosTime($this->opt->getTime()->getTimestamp()); + $footer = $this->buildZip64ExtraBlock(); - return CentralDirectoryFileHeader::generate( - versionMadeBy: ZipStream::ZIP_VERSION_MADE_BY, - versionNeededToExtract:$this->version->value, - generalPurposeBitFlag: $this->generalPurposeBitFlag, - compressionMethod: $this->compressionMethod, - lastModificationDateTime: $this->lastModificationDateTime, - crc32: $this->crc, - compressedSize: $this->compressedSize > 0xFFFFFFFF - ? 0xFFFFFFFF - : $this->compressedSize, - uncompressedSize: $this->uncompressedSize > 0xFFFFFFFF - ? 0xFFFFFFFF - : $this->uncompressedSize, - fileName: $this->fileName, - extraField: $footer, - fileComment: $this->comment, - diskNumberStart: 0, - internalFileAttributes: 0, - externalFileAttributes: 32, - relativeOffsetOfLocalHeader: $this->startOffset > 0xFFFFFFFF - ? 0xFFFFFFFF - : $this->startOffset, - ); + $fields = [ + ['V', ZipStream::CDR_FILE_SIGNATURE], // Central file header signature + ['v', ZipStream::ZIP_VERSION_MADE_BY], // Made by version + ['v', $this->version->getValue()], // Extract by version + ['v', $this->bits], // General purpose bit flags - data descriptor flag set + ['v', $this->method->getValue()], // Compression method + ['V', $time], // Timestamp (DOS Format) + ['V', $this->crc], // CRC32 + ['V', $this->zlen->getLowFF()], // Compressed Data Length + ['V', $this->len->getLowFF()], // Original Data Length + ['v', strlen($name)], // Length of filename + ['v', strlen($footer)], // Extra data len (see above) + ['v', strlen($comment)], // Length of comment + ['v', 0], // Disk number + ['v', 0], // Internal File Attributes + ['V', 32], // External File Attributes + ['V', $this->ofs->getLowFF()], // Relative offset of local header + ]; + + // pack fields, then append name and comment + $header = ZipStream::packFields($fields); + + return $header . $name . $footer . $comment; } - private function isSimulation(): bool + /** + * @return Bigint + */ + public function getTotalLength(): Bigint { - return $this->operationMode === OperationMode::SIMULATE_LAX || $this->operationMode === OperationMode::SIMULATE_STRICT; + return $this->totalLength; + } + + /** + * Convert a UNIX timestamp to a DOS timestamp. + * + * @param int $when + * @return int DOS Timestamp + */ + final protected static function dosTime(int $when): int + { + // get date array for timestamp + $d = getdate($when); + + // set lower-bound on dates + if ($d['year'] < 1980) { + $d = [ + 'year' => 1980, + 'mon' => 1, + 'mday' => 1, + 'hours' => 0, + 'minutes' => 0, + 'seconds' => 0, + ]; + } + + // remove extra years from 1980 + $d['year'] -= 1980; + + // return date string + return + ($d['year'] << 25) | + ($d['mon'] << 21) | + ($d['mday'] << 16) | + ($d['hours'] << 11) | + ($d['minutes'] << 5) | + ($d['seconds'] >> 1); + } + + protected function buildZip64ExtraBlock(bool $force = false): string + { + $fields = []; + if ($this->len->isOver32($force)) { + $fields[] = ['P', $this->len]; // Length of original data + } + + if ($this->len->isOver32($force)) { + $fields[] = ['P', $this->zlen]; // Length of compressed data + } + + if ($this->ofs->isOver32()) { + $fields[] = ['P', $this->ofs]; // Offset of local header record + } + + if (!empty($fields)) { + if (!$this->zip->opt->isEnableZip64()) { + throw new OverflowException(); + } + + array_unshift( + $fields, + ['v', 0x0001], // 64 bit extension + ['v', count($fields) * 8] // Length of data block + ); + $this->version = Version::ZIP64(); + } + + if ($this->bits & self::BIT_EFS_UTF8) { + // Put the tricky entry to + // force Linux unzip to lookup EFS flag. + $fields[] = ['v', 0x5653]; // Choose 'ZS' for proprietary usage + $fields[] = ['v', 0x0000]; // zero length + } + + return ZipStream::packFields($fields); + } + + protected function processStreamWithZeroHeader(StreamInterface $stream): void + { + $this->bits |= self::BIT_ZERO_HEADER; + $this->addFileHeader(); + $this->readStream($stream, self::COMPUTE | self::SEND); + $this->addFileFooter(); + } + + protected function readStream(StreamInterface $stream, ?int $options = null): void + { + $this->deflateInit(); + $total = 0; + $size = $this->opt->getSize(); + while (!$stream->eof() && ($size === 0 || $total < $size)) { + $data = $stream->read(self::CHUNKED_READ_BLOCK_SIZE); + $total += strlen($data); + if ($size > 0 && $total > $size) { + $data = substr($data, 0, strlen($data)-($total - $size)); + } + $this->deflateData($stream, $data, $options); + if ($options & self::SEND) { + $this->zip->send($data); + } + } + $this->deflateFinish($options); + } + + protected function deflateInit(): void + { + $hash = hash_init(self::HASH_ALGORITHM); + $this->hash = $hash; + if ($this->method->equals(Method::DEFLATE())) { + $this->deflate = deflate_init( + ZLIB_ENCODING_RAW, + ['level' => $this->opt->getDeflateLevel()] + ); + } + } + + protected function deflateData(StreamInterface $stream, string &$data, ?int $options = null): void + { + if ($options & self::COMPUTE) { + $this->len = $this->len->add(Bigint::init(strlen($data))); + hash_update($this->hash, $data); + } + if ($this->deflate) { + $data = deflate_add( + $this->deflate, + $data, + $stream->eof() + ? ZLIB_FINISH + : ZLIB_NO_FLUSH + ); + } + if ($options & self::COMPUTE) { + $this->zlen = $this->zlen->add(Bigint::init(strlen($data))); + } + } + + protected function deflateFinish(?int $options = null): void + { + if ($options & self::COMPUTE) { + $this->crc = hexdec(hash_final($this->hash)); + } + } + + protected function processStreamWithComputedHeader(StreamInterface $stream): void + { + $this->readStream($stream, self::COMPUTE); + $stream->rewind(); + + $this->addFileHeader(); + $this->readStream($stream, self::SEND); + $this->addFileFooter(); } } diff --git a/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php b/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php deleted file mode 100644 index 23a66d889..000000000 --- a/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php +++ /dev/null @@ -1,89 +0,0 @@ -value), - new PackField(format: 'V', value: Time::dateTimeToDosTime($lastModificationDateTime)), - new PackField(format: 'V', value: $crc32UncompressedData), - new PackField(format: 'V', value: $compressedSize), - new PackField(format: 'V', value: $uncompressedSize), - new PackField(format: 'v', value: strlen($fileName)), - new PackField(format: 'v', value: strlen($extraField)), - ) . $fileName . $extraField; - } -} diff --git a/vendor/maennchen/zipstream-php/src/OperationMode.php b/vendor/maennchen/zipstream-php/src/OperationMode.php deleted file mode 100644 index dd650f070..000000000 --- a/vendor/maennchen/zipstream-php/src/OperationMode.php +++ /dev/null @@ -1,35 +0,0 @@ - 4 GB or file count > 64k) + * + * @var bool + */ + private $enableZip64 = true; + + /** + * Enable streaming files with single read where + * general purpose bit 3 indicates local file header + * contain zero values in crc and size fields, + * these appear only after file contents + * in data descriptor block. + * + * @var bool + */ + private $zeroHeader = false; + + /** + * Enable reading file stat for determining file size. + * When a 32-bit system reads file size that is + * over 2 GB, invalid value appears in file size + * due to integer overflow. Should be disabled on + * 32-bit systems with method addFileFromPath + * if any file may exceed 2 GB. In this case file + * will be read in blocks and correct size will be + * determined from content. + * + * @var bool + */ + private $statFiles = true; + + /** + * Enable flush after every write to output stream. + * @var bool + */ + private $flushOutput = false; + + /** + * HTTP Content-Disposition. Defaults to + * 'attachment', where + * FILENAME is the specified filename. + * + * Note that this does nothing if you are + * not sending HTTP headers. + * + * @var string + */ + private $contentDisposition = 'attachment'; + + /** + * Note that this does nothing if you are + * not sending HTTP headers. + * + * @var string + */ + private $contentType = 'application/x-zip'; + + /** + * @var int + */ + private $deflateLevel = 6; + + /** + * @var StreamInterface|resource + */ + private $outputStream; + + /** + * Options constructor. + */ + public function __construct() + { + $this->largeFileMethod = Method::STORE(); + $this->outputStream = fopen('php://output', 'wb'); + } + + public function getComment(): string + { + return $this->comment; + } + + public function setComment(string $comment): void + { + $this->comment = $comment; + } + + public function getLargeFileSize(): int + { + return $this->largeFileSize; + } + + public function setLargeFileSize(int $largeFileSize): void + { + $this->largeFileSize = $largeFileSize; + } + + public function getLargeFileMethod(): Method + { + return $this->largeFileMethod; + } + + public function setLargeFileMethod(Method $largeFileMethod): void + { + $this->largeFileMethod = $largeFileMethod; + } + + public function isSendHttpHeaders(): bool + { + return $this->sendHttpHeaders; + } + + public function setSendHttpHeaders(bool $sendHttpHeaders): void + { + $this->sendHttpHeaders = $sendHttpHeaders; + } + + public function getHttpHeaderCallback(): callable + { + return $this->httpHeaderCallback; + } + + public function setHttpHeaderCallback(callable $httpHeaderCallback): void + { + $this->httpHeaderCallback = $httpHeaderCallback; + } + + public function isEnableZip64(): bool + { + return $this->enableZip64; + } + + public function setEnableZip64(bool $enableZip64): void + { + $this->enableZip64 = $enableZip64; + } + + public function isZeroHeader(): bool + { + return $this->zeroHeader; + } + + public function setZeroHeader(bool $zeroHeader): void + { + $this->zeroHeader = $zeroHeader; + } + + public function isFlushOutput(): bool + { + return $this->flushOutput; + } + + public function setFlushOutput(bool $flushOutput): void + { + $this->flushOutput = $flushOutput; + } + + public function isStatFiles(): bool + { + return $this->statFiles; + } + + public function setStatFiles(bool $statFiles): void + { + $this->statFiles = $statFiles; + } + + public function getContentDisposition(): string + { + return $this->contentDisposition; + } + + public function setContentDisposition(string $contentDisposition): void + { + $this->contentDisposition = $contentDisposition; + } + + public function getContentType(): string + { + return $this->contentType; + } + + public function setContentType(string $contentType): void + { + $this->contentType = $contentType; + } + + /** + * @return StreamInterface|resource + */ + public function getOutputStream() + { + return $this->outputStream; + } + + /** + * @param StreamInterface|resource $outputStream + */ + public function setOutputStream($outputStream): void + { + $this->outputStream = $outputStream; + } + + /** + * @return int + */ + public function getDeflateLevel(): int + { + return $this->deflateLevel; + } + + /** + * @param int $deflateLevel + */ + public function setDeflateLevel(int $deflateLevel): void + { + $this->deflateLevel = $deflateLevel; + } +} diff --git a/vendor/maennchen/zipstream-php/src/Option/File.php b/vendor/maennchen/zipstream-php/src/Option/File.php new file mode 100644 index 000000000..37e37ced6 --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Option/File.php @@ -0,0 +1,122 @@ +deflateLevel = $this->deflateLevel ?: $archiveOptions->getDeflateLevel(); + $this->time = $this->time ?: new DateTime(); + } + + /** + * @return string + */ + public function getComment(): string + { + return $this->comment; + } + + /** + * @param string $comment + */ + public function setComment(string $comment): void + { + $this->comment = $comment; + } + + /** + * @return Method + */ + public function getMethod(): Method + { + return $this->method ?: Method::DEFLATE(); + } + + /** + * @param Method $method + */ + public function setMethod(Method $method): void + { + $this->method = $method; + } + + /** + * @return int + */ + public function getDeflateLevel(): int + { + return $this->deflateLevel ?: Archive::DEFAULT_DEFLATE_LEVEL; + } + + /** + * @param int $deflateLevel + */ + public function setDeflateLevel(int $deflateLevel): void + { + $this->deflateLevel = $deflateLevel; + } + + /** + * @return DateTimeInterface + */ + public function getTime(): DateTimeInterface + { + return $this->time; + } + + /** + * @param DateTimeInterface $time + */ + public function setTime(DateTimeInterface $time): void + { + $this->time = $time; + } + + /** + * @return int + */ + public function getSize(): int + { + return $this->size; + } + + /** + * @param int $size + */ + public function setSize(int $size): void + { + $this->size = $size; + } +} diff --git a/vendor/maennchen/zipstream-php/src/Option/Method.php b/vendor/maennchen/zipstream-php/src/Option/Method.php new file mode 100644 index 000000000..0dfce1baf --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Option/Method.php @@ -0,0 +1,23 @@ + + */ +class Method extends Enum +{ + public const STORE = 0x00; + + public const DEFLATE = 0x08; +} diff --git a/vendor/maennchen/zipstream-php/src/Option/Version.php b/vendor/maennchen/zipstream-php/src/Option/Version.php new file mode 100644 index 000000000..f3daa852d --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Option/Version.php @@ -0,0 +1,27 @@ + + */ +class Version extends Enum +{ + public const STORE = 0x000A; // 1.00 + + public const DEFLATE = 0x0014; // 2.00 + + public const ZIP64 = 0x002D; // 4.50 +} diff --git a/vendor/maennchen/zipstream-php/src/PackField.php b/vendor/maennchen/zipstream-php/src/PackField.php deleted file mode 100644 index 3370dd8d0..000000000 --- a/vendor/maennchen/zipstream-php/src/PackField.php +++ /dev/null @@ -1,57 +0,0 @@ -format; - }, ''); - - $args = array_map(function (self $field) { - switch($field->format) { - case 'V': - if ($field->value > self::MAX_V) { - throw new RuntimeException(print_r($field->value, true) . ' is larger than 32 bits'); - } - break; - case 'v': - if ($field->value > self::MAX_v) { - throw new RuntimeException(print_r($field->value, true) . ' is larger than 16 bits'); - } - break; - case 'P': break; - default: - break; - } - - return $field->value; - }, $fields); - - return pack($fmt, ...$args); - } -} diff --git a/vendor/maennchen/zipstream-php/src/Stream.php b/vendor/maennchen/zipstream-php/src/Stream.php new file mode 100644 index 000000000..d80e70f6a --- /dev/null +++ b/vendor/maennchen/zipstream-php/src/Stream.php @@ -0,0 +1,265 @@ +stream = $stream; + } + + /** + * Reads all data from the stream into a string, from the beginning to end. + * + * This method MUST attempt to seek to the beginning of the stream before + * reading data and read the stream until the end is reached. + * + * Warning: This could attempt to load a large amount of data into memory. + * + * This method MUST NOT raise an exception in order to conform with PHP's + * string casting operations. + * + * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring + * @return string + */ + public function __toString(): string + { + try { + $this->seek(0); + } catch (RuntimeException $e) { + } + return (string) stream_get_contents($this->stream); + } + + /** + * Closes the stream and any underlying resources. + * + * @return void + */ + public function close(): void + { + if (is_resource($this->stream)) { + fclose($this->stream); + } + $this->detach(); + } + + /** + * Separates any underlying resources from the stream. + * + * After the stream has been detached, the stream is in an unusable state. + * + * @return resource|null Underlying PHP stream, if any + */ + public function detach() + { + $result = $this->stream; + $this->stream = null; + return $result; + } + + /** + * Seek to a position in the stream. + * + * @link http://www.php.net/manual/en/function.fseek.php + * @param int $offset Stream offset + * @param int $whence Specifies how the cursor position will be calculated + * based on the seek offset. Valid values are identical to the built-in + * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to + * offset bytes SEEK_CUR: Set position to current location plus offset + * SEEK_END: Set position to end-of-stream plus offset. + * @throws RuntimeException on failure. + */ + public function seek($offset, $whence = SEEK_SET): void + { + if (!$this->isSeekable()) { + throw new RuntimeException(); + } + if (fseek($this->stream, $offset, $whence) !== 0) { + throw new RuntimeException(); + } + } + + /** + * Returns whether or not the stream is seekable. + * + * @return bool + */ + public function isSeekable(): bool + { + return (bool)$this->getMetadata('seekable'); + } + + /** + * Get stream metadata as an associative array or retrieve a specific key. + * + * The keys returned are identical to the keys returned from PHP's + * stream_get_meta_data() function. + * + * @link http://php.net/manual/en/function.stream-get-meta-data.php + * @param string $key Specific metadata to retrieve. + * @return array|mixed|null Returns an associative array if no key is + * provided. Returns a specific key value if a key is provided and the + * value is found, or null if the key is not found. + */ + public function getMetadata($key = null) + { + $metadata = stream_get_meta_data($this->stream); + return $key !== null ? @$metadata[$key] : $metadata; + } + + /** + * Get the size of the stream if known. + * + * @return int|null Returns the size in bytes if known, or null if unknown. + */ + public function getSize(): ?int + { + $stats = fstat($this->stream); + return $stats['size']; + } + + /** + * Returns the current position of the file read/write pointer + * + * @return int Position of the file pointer + * @throws RuntimeException on error. + */ + public function tell(): int + { + $position = ftell($this->stream); + if ($position === false) { + throw new RuntimeException(); + } + return $position; + } + + /** + * Returns true if the stream is at the end of the stream. + * + * @return bool + */ + public function eof(): bool + { + return feof($this->stream); + } + + /** + * Seek to the beginning of the stream. + * + * If the stream is not seekable, this method will raise an exception; + * otherwise, it will perform a seek(0). + * + * @see seek() + * @link http://www.php.net/manual/en/function.fseek.php + * @throws RuntimeException on failure. + */ + public function rewind(): void + { + $this->seek(0); + } + + /** + * Write data to the stream. + * + * @param string $string The string that is to be written. + * @return int Returns the number of bytes written to the stream. + * @throws RuntimeException on failure. + */ + public function write($string): int + { + if (!$this->isWritable()) { + throw new RuntimeException(); + } + if (fwrite($this->stream, $string) === false) { + throw new RuntimeException(); + } + return mb_strlen($string); + } + + /** + * Returns whether or not the stream is writable. + * + * @return bool + */ + public function isWritable(): bool + { + $mode = $this->getMetadata('mode'); + if (!is_string($mode)) { + throw new RuntimeException('Could not get stream mode from metadata!'); + } + return preg_match('/[waxc+]/', $mode) === 1; + } + + /** + * Read data from the stream. + * + * @param int $length Read up to $length bytes from the object and return + * them. Fewer than $length bytes may be returned if underlying stream + * call returns fewer bytes. + * @return string Returns the data read from the stream, or an empty string + * if no bytes are available. + * @throws RuntimeException if an error occurs. + */ + public function read($length): string + { + if (!$this->isReadable()) { + throw new RuntimeException(); + } + $result = fread($this->stream, $length); + if ($result === false) { + throw new RuntimeException(); + } + return $result; + } + + /** + * Returns whether or not the stream is readable. + * + * @return bool + */ + public function isReadable(): bool + { + $mode = $this->getMetadata('mode'); + if (!is_string($mode)) { + throw new RuntimeException('Could not get stream mode from metadata!'); + } + return preg_match('/[r+]/', $mode) === 1; + } + + /** + * Returns the remaining contents in a string + * + * @return string + * @throws RuntimeException if unable to read or an error occurs while + * reading. + */ + public function getContents(): string + { + if (!$this->isReadable()) { + throw new RuntimeException(); + } + $result = stream_get_contents($this->stream); + if ($result === false) { + throw new RuntimeException(); + } + return $result; + } +} diff --git a/vendor/maennchen/zipstream-php/src/Time.php b/vendor/maennchen/zipstream-php/src/Time.php deleted file mode 100644 index 4bfba3cc5..000000000 --- a/vendor/maennchen/zipstream-php/src/Time.php +++ /dev/null @@ -1,45 +0,0 @@ -getTimestamp() < $dosMinimumDate->getTimestamp()) { - throw new DosTimeOverflowException(dateTime: $dateTime); - } - - $dateTime = DateTimeImmutable::createFromInterface($dateTime)->sub(new DateInterval('P1980Y')); - - ['year' => $year, - 'mon' => $month, - 'mday' => $day, - 'hours' => $hour, - 'minutes' => $minute, - 'seconds' => $second - ] = getdate($dateTime->getTimestamp()); - - return - ($year << 25) | - ($month << 21) | - ($day << 16) | - ($hour << 11) | - ($minute << 5) | - ($second >> 1); - } -} diff --git a/vendor/maennchen/zipstream-php/src/Version.php b/vendor/maennchen/zipstream-php/src/Version.php deleted file mode 100644 index c014f8a10..000000000 --- a/vendor/maennchen/zipstream-php/src/Version.php +++ /dev/null @@ -1,12 +0,0 @@ -addFile(fileName: 'world.txt', data: 'Hello World'); + * * add first file + * $data = file_get_contents('some_file.gif'); + * $zip->addFile('some_file.gif', $data); * - * // add second file - * $zip->addFile(fileName: 'moon.txt', data: 'Hello Moon'); - * ``` + * * add second file + * $data = file_get_contents('some_file.gif'); + * $zip->addFile('another_file.png', $data); * * 3. Finish the zip stream: * - * ```php - * $zip->finish(); - * ``` + * $zip->finish(); * * You can also add an archive comment, add comments to individual files, * and adjust the timestamp of files. See the API documentation for each * method below for additional information. * - * ## Example + * Example: * - * ```php - * // create a new zip stream object - * $zip = new ZipStream(outputName: 'some_files.zip'); + * // create a new zip stream object + * $zip = new ZipStream('some_files.zip'); * - * // list of local files - * $files = array('foo.txt', 'bar.jpg'); + * // list of local files + * $files = array('foo.txt', 'bar.jpg'); * - * // read and add each file to the archive - * foreach ($files as $path) - * $zip->addFileFormPath(fileName: $path, $path); + * // read and add each file to the archive + * foreach ($files as $path) + * $zip->addFile($path, file_get_contents($path)); * - * // write archive footer to stream - * $zip->finish(); - * ``` + * // write archive footer to stream + * $zip->finish(); */ class ZipStream { @@ -89,776 +80,529 @@ class ZipStream * Here we are using 6 for the OS, indicating OS/2 H.P.F.S. * to prevent file permissions issues upon extract (see #84) * 0x603 is 00000110 00000011 in binary, so 6 and 3 - * - * @internal */ public const ZIP_VERSION_MADE_BY = 0x603; - private bool $ready = true; + /** + * The following signatures end with 0x4b50, which in ASCII is PK, + * the initials of the inventor Phil Katz. + * See https://en.wikipedia.org/wiki/Zip_(file_format)#File_headers + */ + public const FILE_HEADER_SIGNATURE = 0x04034b50; - private int $offset = 0; + public const CDR_FILE_SIGNATURE = 0x02014b50; + + public const CDR_EOF_SIGNATURE = 0x06054b50; + + public const DATA_DESCRIPTOR_SIGNATURE = 0x08074b50; + + public const ZIP64_CDR_EOF_SIGNATURE = 0x06064b50; + + public const ZIP64_CDR_LOCATOR_SIGNATURE = 0x07064b50; /** - * @var string[] + * Global Options + * + * @var ArchiveOptions */ - private array $centralDirectoryRecords = []; + public $opt; /** - * @var resource + * @var array */ - private $outputStream; - - private readonly Closure $httpHeaderCallback; + public $files = []; /** - * @var File[] + * @var Bigint */ - private array $recordedSimulation = []; + public $cdr_ofs; + + /** + * @var Bigint + */ + public $ofs; + + /** + * @var bool + */ + protected $need_headers; + + /** + * @var null|String + */ + protected $output_name; /** * Create a new ZipStream object. * - * ##### Examples + * Parameters: * - * ```php - * // create a new zip file named 'foo.zip' - * $zip = new ZipStream(outputName: 'foo.zip'); + * @param String $name - Name of output file (optional). + * @param ArchiveOptions $opt - Archive Options * - * // create a new zip file named 'bar.zip' with a comment - * $zip = new ZipStream( - * outputName: 'bar.zip', - * comment: 'this is a comment for the zip file.', - * ); - * ``` + * Large File Support: * - * @param OperationMode $operationMode - * The mode can be used to switch between `NORMAL` and `SIMULATION_*` modes. - * For details see the `OperationMode` documentation. + * By default, the method addFileFromPath() will send send files + * larger than 20 megabytes along raw rather than attempting to + * compress them. You can change both the maximum size and the + * compression behavior using the largeFile* options above, with the + * following caveats: * - * Default to `NORMAL`. + * * For "small" files (e.g. files smaller than largeFileSize), the + * memory use can be up to twice that of the actual file. In other + * words, adding a 10 megabyte file to the archive could potentially + * occupy 20 megabytes of memory. * - * @param string $comment - * Archive Level Comment + * * Enabling compression on large files (e.g. files larger than + * large_file_size) is extremely slow, because ZipStream has to pass + * over the large file once to calculate header information, and then + * again to compress and send the actual data. * - * @param StreamInterface|resource|null $outputStream - * Override the output of the archive to a different target. + * Examples: * - * By default the archive is sent to `STDOUT`. + * // create a new zip file named 'foo.zip' + * $zip = new ZipStream('foo.zip'); * - * @param CompressionMethod $defaultCompressionMethod - * How to handle file compression. Legal values are - * `CompressionMethod::DEFLATE` (the default), or - * `CompressionMethod::STORE`. `STORE` sends the file raw and is - * significantly faster, while `DEFLATE` compresses the file and - * is much, much slower. + * // create a new zip file named 'bar.zip' with a comment + * $opt->setComment = 'this is a comment for the zip file.'; + * $zip = new ZipStream('bar.zip', $opt); * - * @param int $defaultDeflateLevel - * Default deflation level. Only relevant if `compressionMethod` - * is `DEFLATE`. + * Notes: * - * See details of [`deflate_init`](https://www.php.net/manual/en/function.deflate-init.php#refsect1-function.deflate-init-parameters) - * - * @param bool $enableZip64 - * Enable Zip64 extension, supporting very large - * archives (any size > 4 GB or file count > 64k) - * - * @param bool $defaultEnableZeroHeader - * Enable streaming files with single read. - * - * When the zero header is set, the file is streamed into the output - * and the size & checksum are added at the end of the file. This is the - * fastest method and uses the least memory. Unfortunately not all - * ZIP clients fully support this and can lead to clients reporting - * the generated ZIP files as corrupted in combination with other - * circumstances. (Zip64 enabled, using UTF8 in comments / names etc.) - * - * When the zero header is not set, the length & checksum need to be - * defined before the file is actually added. To prevent loading all - * the data into memory, the data has to be read twice. If the data - * which is added is not seekable, this call will fail. - * - * @param bool $sendHttpHeaders - * Boolean indicating whether or not to send - * the HTTP headers for this file. - * - * @param ?Closure $httpHeaderCallback - * The method called to send HTTP headers - * - * @param string|null $outputName - * The name of the created archive. - * - * Only relevant if `$sendHttpHeaders = true`. - * - * @param string $contentDisposition - * HTTP Content-Disposition - * - * Only relevant if `sendHttpHeaders = true`. - * - * @param string $contentType - * HTTP Content Type - * - * Only relevant if `sendHttpHeaders = true`. - * - * @param bool $flushOutput - * Enable flush after every write to output stream. - * - * @return self + * In order to let this library send HTTP headers, a filename must be given + * _and_ the option `sendHttpHeaders` must be `true`. This behavior is to + * allow software to send its own headers (including the filename), and + * still use this library. */ - public function __construct( - private OperationMode $operationMode = OperationMode::NORMAL, - private readonly string $comment = '', - $outputStream = null, - private readonly CompressionMethod $defaultCompressionMethod = CompressionMethod::DEFLATE, - private readonly int $defaultDeflateLevel = 6, - private readonly bool $enableZip64 = true, - private readonly bool $defaultEnableZeroHeader = true, - private bool $sendHttpHeaders = true, - ?Closure $httpHeaderCallback = null, - private readonly ?string $outputName = null, - private readonly string $contentDisposition = 'attachment', - private readonly string $contentType = 'application/x-zip', - private bool $flushOutput = false, - ) { - $this->outputStream = self::normalizeStream($outputStream); - $this->httpHeaderCallback = $httpHeaderCallback ?? header(...); + public function __construct(?string $name = null, ?ArchiveOptions $opt = null) + { + $this->opt = $opt ?: new ArchiveOptions(); + + $this->output_name = $name; + $this->need_headers = $name && $this->opt->isSendHttpHeaders(); + + $this->cdr_ofs = new Bigint(); + $this->ofs = new Bigint(); } /** + * addFile + * * Add a file to the archive. * - * ##### File Options + * @param String $name - path of file in archive (including directory). + * @param String $data - contents of file + * @param FileOptions $options * - * See {@see addFileFromPsr7Stream()} + * File Options: + * time - Last-modified timestamp (seconds since the epoch) of + * this file. Defaults to the current time. + * comment - Comment related to this file. + * method - Storage method for file ("store" or "deflate") * - * ##### Examples + * Examples: * - * ```php - * // add a file named 'world.txt' - * $zip->addFile(fileName: 'world.txt', data: 'Hello World!'); + * // add a file named 'foo.txt' + * $data = file_get_contents('foo.txt'); + * $zip->addFile('foo.txt', $data); * - * // add a file named 'bar.jpg' with a comment and a last-modified - * // time of two hours ago - * $zip->addFile( - * fileName: 'bar.jpg', - * data: $data, - * comment: 'this is a comment about bar.jpg', - * lastModificationDateTime: new DateTime('2 hours ago'), - * ); - * ``` - * - * @param string $data - * - * contents of file + * // add a file named 'bar.jpg' with a comment and a last-modified + * // time of two hours ago + * $data = file_get_contents('bar.jpg'); + * $opt->setTime = time() - 2 * 3600; + * $opt->setComment = 'this is a comment about bar.jpg'; + * $zip->addFile('bar.jpg', $data, $opt); */ - public function addFile( - string $fileName, - string $data, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, - ): void { - $this->addFileFromCallback( - fileName: $fileName, - callback: fn () => $data, - comment: $comment, - compressionMethod: $compressionMethod, - deflateLevel: $deflateLevel, - lastModificationDateTime: $lastModificationDateTime, - maxSize: $maxSize, - exactSize: $exactSize, - enableZeroHeader: $enableZeroHeader, - ); + public function addFile(string $name, string $data, ?FileOptions $options = null): void + { + $options = $options ?: new FileOptions(); + $options->defaultTo($this->opt); + + $file = new File($this, $name, $options); + $file->processData($data); } /** + * addFileFromPath + * * Add a file at path to the archive. * - * ##### File Options + * Note that large files may be compressed differently than smaller + * files; see the "Large File Support" section above for more + * information. * - * See {@see addFileFromPsr7Stream()} + * @param String $name - name of file in archive (including directory path). + * @param String $path - path to file on disk (note: paths should be encoded using + * UNIX-style forward slashes -- e.g '/path/to/some/file'). + * @param FileOptions $options * - * ###### Examples + * File Options: + * time - Last-modified timestamp (seconds since the epoch) of + * this file. Defaults to the current time. + * comment - Comment related to this file. + * method - Storage method for file ("store" or "deflate") * - * ```php - * // add a file named 'foo.txt' from the local file '/tmp/foo.txt' - * $zip->addFileFromPath( - * fileName: 'foo.txt', - * path: '/tmp/foo.txt', - * ); + * Examples: * - * // add a file named 'bigfile.rar' from the local file - * // '/usr/share/bigfile.rar' with a comment and a last-modified - * // time of two hours ago - * $zip->addFile( - * fileName: 'bigfile.rar', - * path: '/usr/share/bigfile.rar', - * comment: 'this is a comment about bigfile.rar', - * lastModificationDateTime: new DateTime('2 hours ago'), - * ); - * ``` + * // add a file named 'foo.txt' from the local file '/tmp/foo.txt' + * $zip->addFileFromPath('foo.txt', '/tmp/foo.txt'); * + * // add a file named 'bigfile.rar' from the local file + * // '/usr/share/bigfile.rar' with a comment and a last-modified + * // time of two hours ago + * $path = '/usr/share/bigfile.rar'; + * $opt->setTime = time() - 2 * 3600; + * $opt->setComment = 'this is a comment about bar.jpg'; + * $zip->addFileFromPath('bigfile.rar', $path, $opt); + * + * @return void * @throws \ZipStream\Exception\FileNotFoundException * @throws \ZipStream\Exception\FileNotReadableException */ - public function addFileFromPath( - /** - * name of file in archive (including directory path). - */ - string $fileName, + public function addFileFromPath(string $name, string $path, ?FileOptions $options = null): void + { + $options = $options ?: new FileOptions(); + $options->defaultTo($this->opt); - /** - * path to file on disk (note: paths should be encoded using - * UNIX-style forward slashes -- e.g '/path/to/some/file'). - */ - string $path, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, - ): void { - if (!is_readable($path)) { - if (!file_exists($path)) { - throw new FileNotFoundException($path); - } - throw new FileNotReadableException($path); - } - - if ($fileTime = filemtime($path)) { - $lastModificationDateTime ??= (new DateTimeImmutable())->setTimestamp($fileTime); - } - - $this->addFileFromCallback( - fileName: $fileName, - callback: function () use ($path) { - - $stream = fopen($path, 'rb'); - - if (!$stream) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('fopen'); - // @codeCoverageIgnoreEnd - } - - return $stream; - }, - comment: $comment, - compressionMethod: $compressionMethod, - deflateLevel: $deflateLevel, - lastModificationDateTime: $lastModificationDateTime, - maxSize: $maxSize, - exactSize: $exactSize, - enableZeroHeader: $enableZeroHeader, - ); + $file = new File($this, $name, $options); + $file->processPath($path); } /** - * Add an open stream (resource) to the archive. + * addFileFromStream * - * ##### File Options - * - * See {@see addFileFromPsr7Stream()} - * - * ##### Examples - * - * ```php - * // create a temporary file stream and write text to it - * $filePointer = tmpfile(); - * fwrite($filePointer, 'The quick brown fox jumped over the lazy dog.'); - * - * // add a file named 'streamfile.txt' from the content of the stream - * $archive->addFileFromStream( - * fileName: 'streamfile.txt', - * stream: $filePointer, - * ); - * ``` - * - * @param resource $stream contents of file as a stream resource - */ - public function addFileFromStream( - string $fileName, - $stream, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, - ): void { - $this->addFileFromCallback( - fileName: $fileName, - callback: fn () => $stream, - comment: $comment, - compressionMethod: $compressionMethod, - deflateLevel: $deflateLevel, - lastModificationDateTime: $lastModificationDateTime, - maxSize: $maxSize, - exactSize: $exactSize, - enableZeroHeader: $enableZeroHeader, - ); - } - - /** * Add an open stream to the archive. * - * ##### Examples + * @param String $name - path of file in archive (including directory). + * @param resource $stream - contents of file as a stream resource + * @param FileOptions $options * - * ```php - * $stream = $response->getBody(); - * // add a file named 'streamfile.txt' from the content of the stream - * $archive->addFileFromPsr7Stream( - * fileName: 'streamfile.txt', - * stream: $stream, - * ); - * ``` + * File Options: + * time - Last-modified timestamp (seconds since the epoch) of + * this file. Defaults to the current time. + * comment - Comment related to this file. * - * @param string $fileName - * path of file in archive (including directory) + * Examples: * - * @param StreamInterface $stream - * contents of file as a stream resource + * // create a temporary file stream and write text to it + * $fp = tmpfile(); + * fwrite($fp, 'The quick brown fox jumped over the lazy dog.'); * - * @param string $comment - * ZIP comment for this file + * // add a file named 'streamfile.txt' from the content of the stream + * $x->addFileFromStream('streamfile.txt', $fp); * - * @param ?CompressionMethod $compressionMethod - * Override `defaultCompressionMethod` + * @return void + */ + public function addFileFromStream(string $name, $stream, ?FileOptions $options = null): void + { + $options = $options ?: new FileOptions(); + $options->defaultTo($this->opt); + + $file = new File($this, $name, $options); + $file->processStream(new Stream($stream)); + } + + /** + * addFileFromPsr7Stream * - * See {@see __construct()} + * Add an open stream to the archive. * - * @param ?int $deflateLevel - * Override `defaultDeflateLevel` + * @param String $name - path of file in archive (including directory). + * @param StreamInterface $stream - contents of file as a stream resource + * @param FileOptions $options * - * See {@see __construct()} + * File Options: + * time - Last-modified timestamp (seconds since the epoch) of + * this file. Defaults to the current time. + * comment - Comment related to this file. * - * @param ?DateTimeInterface $lastModificationDateTime - * Set last modification time of file. + * Examples: * - * Default: `now` + * $stream = $response->getBody(); + * // add a file named 'streamfile.txt' from the content of the stream + * $x->addFileFromPsr7Stream('streamfile.txt', $stream); * - * @param ?int $maxSize - * Only read `maxSize` bytes from file. - * - * The file is considered done when either reaching `EOF` - * or the `maxSize`. - * - * @param ?int $exactSize - * Read exactly `exactSize` bytes from file. - * If `EOF` is reached before reading `exactSize` bytes, an error will be - * thrown. The parameter allows for faster size calculations if the `stream` - * does not support `fstat` size or is slow and otherwise known beforehand. - * - * @param ?bool $enableZeroHeader - * Override `defaultEnableZeroHeader` - * - * See {@see __construct()} + * @return void */ public function addFileFromPsr7Stream( - string $fileName, + string $name, StreamInterface $stream, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, + ?FileOptions $options = null ): void { - $this->addFileFromCallback( - fileName: $fileName, - callback: fn () => $stream, - comment: $comment, - compressionMethod: $compressionMethod, - deflateLevel: $deflateLevel, - lastModificationDateTime: $lastModificationDateTime, - maxSize: $maxSize, - exactSize: $exactSize, - enableZeroHeader: $enableZeroHeader, - ); + $options = $options ?: new FileOptions(); + $options->defaultTo($this->opt); + + $file = new File($this, $name, $options); + $file->processStream($stream); } /** - * Add a file based on a callback. + * finish * - * This is useful when you want to simulate a lot of files without keeping - * all of the file handles open at the same time. - * - * ##### Examples - * - * ```php - * foreach($files as $name => $size) { - * $archive->addFileFromPsr7Stream( - * fileName: 'streamfile.txt', - * exactSize: $size, - * callback: function() use($name): Psr\Http\Message\StreamInterface { - * $response = download($name); - * return $response->getBody(); - * } - * ); - * } - * ``` - * - * @param string $fileName - * path of file in archive (including directory) - * - * @param Closure $callback - * @psalm-param Closure(): (resource|StreamInterface|string) $callback - * A callback to get the file contents in the shape of a PHP stream, - * a Psr StreamInterface implementation, or a string. - * - * @param string $comment - * ZIP comment for this file - * - * @param ?CompressionMethod $compressionMethod - * Override `defaultCompressionMethod` - * - * See {@see __construct()} - * - * @param ?int $deflateLevel - * Override `defaultDeflateLevel` - * - * See {@see __construct()} - * - * @param ?DateTimeInterface $lastModificationDateTime - * Set last modification time of file. - * - * Default: `now` - * - * @param ?int $maxSize - * Only read `maxSize` bytes from file. - * - * The file is considered done when either reaching `EOF` - * or the `maxSize`. - * - * @param ?int $exactSize - * Read exactly `exactSize` bytes from file. - * If `EOF` is reached before reading `exactSize` bytes, an error will be - * thrown. The parameter allows for faster size calculations if the `stream` - * does not support `fstat` size or is slow and otherwise known beforehand. - * - * @param ?bool $enableZeroHeader - * Override `defaultEnableZeroHeader` - * - * See {@see __construct()} - */ - public function addFileFromCallback( - string $fileName, - Closure $callback, - string $comment = '', - ?CompressionMethod $compressionMethod = null, - ?int $deflateLevel = null, - ?DateTimeInterface $lastModificationDateTime = null, - ?int $maxSize = null, - ?int $exactSize = null, - ?bool $enableZeroHeader = null, - ): void { - $file = new File( - dataCallback: function () use ($callback, $maxSize) { - $data = $callback(); - - if(is_resource($data)) { - return $data; - } - - if($data instanceof StreamInterface) { - return StreamWrapper::getResource($data); - } - - - $stream = fopen('php://memory', 'rw+'); - if ($stream === false) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('fopen'); - // @codeCoverageIgnoreEnd - } - if ($maxSize !== null && fwrite($stream, $data, $maxSize) === false) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('fwrite', $stream); - // @codeCoverageIgnoreEnd - } elseif (fwrite($stream, $data) === false) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('fwrite', $stream); - // @codeCoverageIgnoreEnd - } - if (rewind($stream) === false) { - // @codeCoverageIgnoreStart - throw new ResourceActionException('rewind', $stream); - // @codeCoverageIgnoreEnd - } - - return $stream; - - }, - send: $this->send(...), - recordSentBytes: $this->recordSentBytes(...), - operationMode: $this->operationMode, - fileName: $fileName, - startOffset: $this->offset, - compressionMethod: $compressionMethod ?? $this->defaultCompressionMethod, - comment: $comment, - deflateLevel: $deflateLevel ?? $this->defaultDeflateLevel, - lastModificationDateTime: $lastModificationDateTime ?? new DateTimeImmutable(), - maxSize: $maxSize, - exactSize: $exactSize, - enableZip64: $this->enableZip64, - enableZeroHeader: $enableZeroHeader ?? $this->defaultEnableZeroHeader, - ); - - if($this->operationMode !== OperationMode::NORMAL) { - $this->recordedSimulation[] = $file; - } - - $this->centralDirectoryRecords[] = $file->process(); - } - - /** - * Add a directory to the archive. - * - * ##### File Options - * - * See {@see addFileFromPsr7Stream()} - * - * ##### Examples - * - * ```php - * // add a directory named 'world/' - * $zip->addFile(fileName: 'world/'); - * ``` - */ - public function addDirectory( - string $fileName, - string $comment = '', - ?DateTimeInterface $lastModificationDateTime = null, - ): void { - if (!str_ends_with($fileName, '/')) { - $fileName .= '/'; - } - - $this->addFile( - fileName: $fileName, - data: '', - comment: $comment, - compressionMethod: CompressionMethod::STORE, - deflateLevel: null, - lastModificationDateTime: $lastModificationDateTime, - maxSize: 0, - exactSize: 0, - enableZeroHeader: false, - ); - } - - /** - * Executes a previously calculated simulation. - * - * ##### Example - * - * ```php - * $zip = new ZipStream( - * outputName: 'foo.zip', - * operationMode: OperationMode::SIMULATE_STRICT, - * ); - * - * $zip->addFile('test.txt', 'Hello World'); - * - * $size = $zip->finish(); - * - * header('Content-Length: '. $size); - * - * $zip->executeSimulation(); - * ``` - */ - public function executeSimulation(): void - { - if($this->operationMode !== OperationMode::NORMAL) { - throw new RuntimeException('Zip simulation is not finished.'); - } - - foreach($this->recordedSimulation as $file) { - $this->centralDirectoryRecords[] = $file->cloneSimulationExecution()->process(); - } - - $this->finish(); - } - - /** * Write zip footer to stream. * - * The clase is left in an unusable state after `finish`. + * Example: * - * ##### Example + * // add a list of files to the archive + * $files = array('foo.txt', 'bar.jpg'); + * foreach ($files as $path) + * $zip->addFile($path, file_get_contents($path)); * - * ```php - * // write footer to stream - * $zip->finish(); - * ``` + * // write footer to stream + * $zip->finish(); + * @return void + * + * @throws OverflowException */ - public function finish(): int + public function finish(): void { - $centralDirectoryStartOffsetOnDisk = $this->offset; - $sizeOfCentralDirectory = 0; - // add trailing cdr file records - foreach ($this->centralDirectoryRecords as $centralDirectoryRecord) { - $this->send($centralDirectoryRecord); - $sizeOfCentralDirectory += strlen($centralDirectoryRecord); + foreach ($this->files as $cdrFile) { + $this->send($cdrFile); + $this->cdr_ofs = $this->cdr_ofs->add(Bigint::init(strlen($cdrFile))); } // Add 64bit headers (if applicable) - if (count($this->centralDirectoryRecords) >= 0xFFFF || - $centralDirectoryStartOffsetOnDisk > 0xFFFFFFFF || - $sizeOfCentralDirectory > 0xFFFFFFFF) { - if (!$this->enableZip64) { + if (count($this->files) >= 0xFFFF || + $this->cdr_ofs->isOver32() || + $this->ofs->isOver32()) { + if (!$this->opt->isEnableZip64()) { throw new OverflowException(); } - $this->send(Zip64\EndOfCentralDirectory::generate( - versionMadeBy: self::ZIP_VERSION_MADE_BY, - versionNeededToExtract: Version::ZIP64->value, - numberOfThisDisk: 0, - numberOfTheDiskWithCentralDirectoryStart: 0, - numberOfCentralDirectoryEntriesOnThisDisk: count($this->centralDirectoryRecords), - numberOfCentralDirectoryEntries: count($this->centralDirectoryRecords), - sizeOfCentralDirectory: $sizeOfCentralDirectory, - centralDirectoryStartOffsetOnDisk: $centralDirectoryStartOffsetOnDisk, - extensibleDataSector: '', - )); - - $this->send(Zip64\EndOfCentralDirectoryLocator::generate( - numberOfTheDiskWithZip64CentralDirectoryStart: 0x00, - zip64centralDirectoryStartOffsetOnDisk: $centralDirectoryStartOffsetOnDisk + $sizeOfCentralDirectory, - totalNumberOfDisks: 1, - )); + $this->addCdr64Eof(); + $this->addCdr64Locator(); } // add trailing cdr eof record - $numberOfCentralDirectoryEntries = min(count($this->centralDirectoryRecords), 0xFFFF); - $this->send(EndOfCentralDirectory::generate( - numberOfThisDisk: 0x00, - numberOfTheDiskWithCentralDirectoryStart: 0x00, - numberOfCentralDirectoryEntriesOnThisDisk: $numberOfCentralDirectoryEntries, - numberOfCentralDirectoryEntries: $numberOfCentralDirectoryEntries, - sizeOfCentralDirectory: min($sizeOfCentralDirectory, 0xFFFFFFFF), - centralDirectoryStartOffsetOnDisk: min($centralDirectoryStartOffsetOnDisk, 0xFFFFFFFF), - zipFileComment: $this->comment, - )); - - $size = $this->offset; + $this->addCdrEof(); // The End $this->clear(); - - return $size; } /** - * @param StreamInterface|resource|null $outputStream - * @return resource + * Create a format string and argument list for pack(), then call + * pack() and return the result. + * + * @param array $fields + * @return string */ - private static function normalizeStream($outputStream) + public static function packFields(array $fields): string { - if ($outputStream instanceof StreamInterface) { - return StreamWrapper::getResource($outputStream); - } - if (is_resource($outputStream)) { - return $outputStream; - } - return fopen('php://output', 'wb'); - } + $fmt = ''; + $args = []; - /** - * Record sent bytes - */ - private function recordSentBytes(int $sentBytes): void - { - $this->offset += $sentBytes; + // populate format string and argument list + foreach ($fields as [$format, $value]) { + if ($format === 'P') { + $fmt .= 'VV'; + if ($value instanceof Bigint) { + $args[] = $value->getLow32(); + $args[] = $value->getHigh32(); + } else { + $args[] = $value; + $args[] = 0; + } + } else { + if ($value instanceof Bigint) { + $value = $value->getLow32(); + } + $fmt .= $format; + $args[] = $value; + } + } + + // prepend format string to argument list + array_unshift($args, $fmt); + + // build output string from header and compressed data + return pack(...$args); } /** * Send string, sending HTTP headers if necessary. * Flush output after write if configure option is set. + * + * @param String $str + * @return void */ - private function send(string $data): void + public function send(string $str): void { - if (!$this->ready) { - throw new RuntimeException('Archive is already finished'); - } - - if ($this->operationMode === OperationMode::NORMAL && $this->sendHttpHeaders) { + if ($this->need_headers) { $this->sendHttpHeaders(); - $this->sendHttpHeaders = false; + } + $this->need_headers = false; + + $outputStream = $this->opt->getOutputStream(); + + if ($outputStream instanceof StreamInterface) { + $outputStream->write($str); + } else { + fwrite($outputStream, $str); } - $this->recordSentBytes(strlen($data)); - - if ($this->operationMode === OperationMode::NORMAL) { - if (fwrite($this->outputStream, $data) === false) { - throw new ResourceActionException('fwrite', $this->outputStream); + if ($this->opt->isFlushOutput()) { + // flush output buffer if it is on and flushable + $status = ob_get_status(); + if (isset($status['flags']) && ($status['flags'] & PHP_OUTPUT_HANDLER_FLUSHABLE)) { + ob_flush(); } - if ($this->flushOutput) { - // flush output buffer if it is on and flushable - $status = ob_get_status(); - if (isset($status['flags']) && is_int($status['flags']) && ($status['flags'] & PHP_OUTPUT_HANDLER_FLUSHABLE)) { - ob_flush(); - } - - // Flush system buffers after flushing userspace output buffer - flush(); - } + // Flush system buffers after flushing userspace output buffer + flush(); } } - /** - * Send HTTP headers for this stream. + /** + * Is this file larger than large_file_size? + * + * @param string $path + * @return bool */ - private function sendHttpHeaders(): void + public function isLargeFile(string $path): bool + { + if (!$this->opt->isStatFiles()) { + return false; + } + $stat = stat($path); + return $stat['size'] > $this->opt->getLargeFileSize(); + } + + /** + * Save file attributes for trailing CDR record. + * + * @param File $file + * @return void + */ + public function addToCdr(File $file): void + { + $file->ofs = $this->ofs; + $this->ofs = $this->ofs->add($file->getTotalLength()); + $this->files[] = $file->getCdrFile(); + } + + /** + * Send ZIP64 CDR EOF (Central Directory Record End-of-File) record. + * + * @return void + */ + protected function addCdr64Eof(): void + { + $num_files = count($this->files); + $cdr_length = $this->cdr_ofs; + $cdr_offset = $this->ofs; + + $fields = [ + ['V', static::ZIP64_CDR_EOF_SIGNATURE], // ZIP64 end of central file header signature + ['P', 44], // Length of data below this header (length of block - 12) = 44 + ['v', static::ZIP_VERSION_MADE_BY], // Made by version + ['v', Version::ZIP64], // Extract by version + ['V', 0x00], // disk number + ['V', 0x00], // no of disks + ['P', $num_files], // no of entries on disk + ['P', $num_files], // no of entries in cdr + ['P', $cdr_length], // CDR size + ['P', $cdr_offset], // CDR offset + ]; + + $ret = static::packFields($fields); + $this->send($ret); + } + + /** + * Send HTTP headers for this stream. + * + * @return void + */ + protected function sendHttpHeaders(): void { // grab content disposition - $disposition = $this->contentDisposition; + $disposition = $this->opt->getContentDisposition(); - if ($this->outputName) { + if ($this->output_name) { // Various different browsers dislike various characters here. Strip them all for safety. - $safeOutput = trim(str_replace(['"', "'", '\\', ';', "\n", "\r"], '', $this->outputName)); + $safe_output = trim(str_replace(['"', "'", '\\', ';', "\n", "\r"], '', $this->output_name)); // Check if we need to UTF-8 encode the filename - $urlencoded = rawurlencode($safeOutput); + $urlencoded = rawurlencode($safe_output); $disposition .= "; filename*=UTF-8''{$urlencoded}"; } $headers = [ - 'Content-Type' => $this->contentType, + 'Content-Type' => $this->opt->getContentType(), 'Content-Disposition' => $disposition, 'Pragma' => 'public', 'Cache-Control' => 'public, must-revalidate', 'Content-Transfer-Encoding' => 'binary', ]; + $call = $this->opt->getHttpHeaderCallback(); foreach ($headers as $key => $val) { - ($this->httpHeaderCallback)("$key: $val"); + $call("$key: $val"); } } + /** + * Send ZIP64 CDR Locator (Central Directory Record Locator) record. + * + * @return void + */ + protected function addCdr64Locator(): void + { + $cdr_offset = $this->ofs->add($this->cdr_ofs); + + $fields = [ + ['V', static::ZIP64_CDR_LOCATOR_SIGNATURE], // ZIP64 end of central file header signature + ['V', 0x00], // Disc number containing CDR64EOF + ['P', $cdr_offset], // CDR offset + ['V', 1], // Total number of disks + ]; + + $ret = static::packFields($fields); + $this->send($ret); + } + + /** + * Send CDR EOF (Central Directory Record End-of-File) record. + * + * @return void + */ + protected function addCdrEof(): void + { + $num_files = count($this->files); + $cdr_length = $this->cdr_ofs; + $cdr_offset = $this->ofs; + + // grab comment (if specified) + $comment = $this->opt->getComment(); + + $fields = [ + ['V', static::CDR_EOF_SIGNATURE], // end of central file header signature + ['v', 0x00], // disk number + ['v', 0x00], // no of disks + ['v', min($num_files, 0xFFFF)], // no of entries on disk + ['v', min($num_files, 0xFFFF)], // no of entries in cdr + ['V', $cdr_length->getLowFF()], // CDR size + ['V', $cdr_offset->getLowFF()], // CDR offset + ['v', strlen($comment)], // Zip Comment size + ]; + + $ret = static::packFields($fields) . $comment; + $this->send($ret); + } + /** * Clear all internal variables. Note that the stream object is not * usable after this. + * + * @return void */ - private function clear(): void + protected function clear(): void { - $this->centralDirectoryRecords = []; - $this->offset = 0; - - if($this->operationMode === OperationMode::NORMAL) { - $this->ready = false; - $this->recordedSimulation = []; - } else { - $this->operationMode = OperationMode::NORMAL; - } + $this->files = []; + $this->ofs = new Bigint(); + $this->cdr_ofs = new Bigint(); + $this->opt = new ArchiveOptions(); } } diff --git a/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php b/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php deleted file mode 100644 index bf621bc09..000000000 --- a/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php +++ /dev/null @@ -1,23 +0,0 @@ -fail("File {$filePath} must contain {$needle}"); - } - - protected function assertFileDoesNotContain(string $filePath, string $needle): void - { - $last = ''; - - $handle = fopen($filePath, 'r'); - while (!feof($handle)) { - $line = fgets($handle, 1024); - - if(str_contains($last . $line, $needle)) { - fclose($handle); - - $this->fail("File {$filePath} must not contain {$needle}"); - } - - $last = $line; - } - - fclose($handle); - } -} diff --git a/vendor/maennchen/zipstream-php/test/BigintTest.php b/vendor/maennchen/zipstream-php/test/BigintTest.php new file mode 100644 index 000000000..4d26fcd0b --- /dev/null +++ b/vendor/maennchen/zipstream-php/test/BigintTest.php @@ -0,0 +1,66 @@ +assertSame('0x0000000012345678', $bigint->getHex64()); + $this->assertSame(0x12345678, $bigint->getLow32()); + $this->assertSame(0, $bigint->getHigh32()); + } + + public function testConstructLarge(): void + { + $bigint = new Bigint(0x87654321); + $this->assertSame('0x0000000087654321', $bigint->getHex64()); + $this->assertSame('87654321', bin2hex(pack('N', $bigint->getLow32()))); + $this->assertSame(0, $bigint->getHigh32()); + } + + public function testAddSmallValue(): void + { + $bigint = new Bigint(1); + $bigint = $bigint->add(Bigint::init(2)); + $this->assertSame(3, $bigint->getLow32()); + $this->assertFalse($bigint->isOver32()); + $this->assertTrue($bigint->isOver32(true)); + $this->assertSame($bigint->getLowFF(), (float)$bigint->getLow32()); + $this->assertSame($bigint->getLowFF(true), (float)0xFFFFFFFF); + } + + public function testAddWithOverflowAtLowestByte(): void + { + $bigint = new Bigint(0xFF); + $bigint = $bigint->add(Bigint::init(0x01)); + $this->assertSame(0x100, $bigint->getLow32()); + } + + public function testAddWithOverflowAtInteger32(): void + { + $bigint = new Bigint(0xFFFFFFFE); + $this->assertFalse($bigint->isOver32()); + $bigint = $bigint->add(Bigint::init(0x01)); + $this->assertTrue($bigint->isOver32()); + $bigint = $bigint->add(Bigint::init(0x01)); + $this->assertSame('0x0000000100000000', $bigint->getHex64()); + $this->assertTrue($bigint->isOver32()); + $this->assertSame((float)0xFFFFFFFF, $bigint->getLowFF()); + } + + public function testAddWithOverflowAtInteger64(): void + { + $bigint = Bigint::fromLowHigh(0xFFFFFFFF, 0xFFFFFFFF); + $this->assertSame('0xFFFFFFFFFFFFFFFF', $bigint->getHex64()); + $this->expectException(OverflowException::class); + $bigint->add(Bigint::init(1)); + } +} diff --git a/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php b/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php deleted file mode 100644 index 5457b4f44..000000000 --- a/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php +++ /dev/null @@ -1,60 +0,0 @@ -assertSame( - bin2hex($header), - '504b0102' . // 4 bytes; central file header signature - '0306' . // 2 bytes; version made by - '2d00' . // 2 bytes; version needed to extract - '2222' . // 2 bytes; general purpose bit flag - '0800' . // 2 bytes; compression method - '2008' . // 2 bytes; last mod file time - '2154' . // 2 bytes; last mod file date - '11111111' . // 4 bytes; crc-32 - '77777777' . // 4 bytes; compressed size - '99999999' . // 4 bytes; uncompressed size - '0800' . // 2 bytes; file name length (n) - '0c00' . // 2 bytes; extra field length (m) - '0c00' . // 2 bytes; file comment length (o) - '0000' . // 2 bytes; disk number start - '0000' . // 2 bytes; internal file attributes - '20000000' . // 4 bytes; external file attributes - '34120000' . // 4 bytes; relative offset of local header - '746573742e706e67' . // n bytes; file name - '736f6d6520636f6e74656e74' . // m bytes; extra field - '736f6d6520636f6d6d656e74' // o bytes; file comment - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php b/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php deleted file mode 100644 index cc886c74b..000000000 --- a/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php +++ /dev/null @@ -1,26 +0,0 @@ -assertSame( - bin2hex(DataDescriptor::generate( - crc32UncompressedData: 0x11111111, - compressedSize: 0x77777777, - uncompressedSize: 0x99999999, - )), - '504b0708' . // 4 bytes; Optional data descriptor signature = 0x08074b50 - '11111111' . // 4 bytes; CRC-32 of uncompressed data - '77777777' . // 4 bytes; Compressed size - '99999999' // 4 bytes; Uncompressed size - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php b/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php deleted file mode 100644 index be0a90743..000000000 --- a/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php +++ /dev/null @@ -1,35 +0,0 @@ -assertSame( - bin2hex(EndOfCentralDirectory::generate( - numberOfThisDisk: 0x00, - numberOfTheDiskWithCentralDirectoryStart: 0x00, - numberOfCentralDirectoryEntriesOnThisDisk: 0x10, - numberOfCentralDirectoryEntries: 0x10, - sizeOfCentralDirectory: 0x22, - centralDirectoryStartOffsetOnDisk: 0x33, - zipFileComment: 'foo', - )), - '504b0506' . // 4 bytes; end of central dir signature 0x06054b50 - '0000' . // 2 bytes; number of this disk - '0000' . // 2 bytes; number of the disk with the start of the central directory - '1000' . // 2 bytes; total number of entries in the central directory on this disk - '1000' . // 2 bytes; total number of entries in the central directory - '22000000' . // 4 bytes; size of the central directory - '33000000' . // 4 bytes; offset of start of central directory with respect to the starting disk number - '0300' . // 2 bytes; .ZIP file comment length - bin2hex('foo') - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php b/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php deleted file mode 100644 index 4f1cf5c32..000000000 --- a/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php +++ /dev/null @@ -1,106 +0,0 @@ -detach(); - } - - /** - * @return null - */ - public function detach() - { - return; - } - - public function getSize(): ?int - { - return null; - } - - public function tell(): int - { - return $this->offset; - } - - public function eof(): bool - { - return false; - } - - public function isSeekable(): bool - { - return true; - } - - public function seek(int $offset, int $whence = SEEK_SET): void - { - switch($whence) { - case SEEK_SET: - $this->offset = $offset; - break; - case SEEK_CUR: - $this->offset += $offset; - break; - case SEEK_END: - throw new RuntimeException('Infinite Stream!'); - break; - } - } - - public function rewind(): void - { - $this->seek(0); - } - - public function isWritable(): bool - { - return false; - } - - public function write(string $string): int - { - throw new RuntimeException('Not writeable'); - } - - public function isReadable(): bool - { - return true; - } - - public function read(int $length): string - { - $this->offset += $length; - return substr(str_repeat($this->toRepeat, (int) ceil($length / strlen($this->toRepeat))), 0, $length); - } - - public function getContents(): string - { - throw new RuntimeException('Infinite Stream!'); - } - - public function getMetadata(?string $key = null): array|null - { - return $key !== null ? null : []; - } -} diff --git a/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php b/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php deleted file mode 100644 index 3d4440e8a..000000000 --- a/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php +++ /dev/null @@ -1,141 +0,0 @@ -context); - - if (!isset($options[self::NAME]['injectFaults'])) { - return false; - } - - $this->mode = $mode; - $this->injectFaults = $options[self::NAME]['injectFaults']; - - if ($this->shouldFail(__FUNCTION__)) { - return false; - } - - return true; - } - - public function stream_write(string $data) - { - if ($this->shouldFail(__FUNCTION__)) { - return false; - } - return true; - } - - public function stream_eof() - { - return true; - } - - public function stream_seek(int $offset, int $whence): bool - { - if ($this->shouldFail(__FUNCTION__)) { - return false; - } - - return true; - } - - public function stream_tell(): int - { - if ($this->shouldFail(__FUNCTION__)) { - return false; - } - - return 0; - } - - public static function register(): void - { - if (!in_array(self::NAME, stream_get_wrappers(), true)) { - stream_wrapper_register(self::NAME, __CLASS__); - } - } - - public function stream_stat(): array - { - static $modeMap = [ - 'r' => 33060, - 'rb' => 33060, - 'r+' => 33206, - 'w' => 33188, - 'wb' => 33188, - ]; - - return [ - 'dev' => 0, - 'ino' => 0, - 'mode' => $modeMap[$this->mode], - 'nlink' => 0, - 'uid' => 0, - 'gid' => 0, - 'rdev' => 0, - 'size' => 0, - 'atime' => 0, - 'mtime' => 0, - 'ctime' => 0, - 'blksize' => 0, - 'blocks' => 0, - ]; - } - - public function url_stat(string $path, int $flags): array - { - return [ - 'dev' => 0, - 'ino' => 0, - 'mode' => 0, - 'nlink' => 0, - 'uid' => 0, - 'gid' => 0, - 'rdev' => 0, - 'size' => 0, - 'atime' => 0, - 'mtime' => 0, - 'ctime' => 0, - 'blksize' => 0, - 'blocks' => 0, - ]; - } - - private static function createStreamContext(array $injectFaults) - { - return stream_context_create([ - self::NAME => ['injectFaults' => $injectFaults], - ]); - } - - private function shouldFail(string $function): bool - { - return in_array($function, $this->injectFaults, true); - } -} diff --git a/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php b/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php deleted file mode 100644 index 196dd0fe3..000000000 --- a/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php +++ /dev/null @@ -1,47 +0,0 @@ -assertSame( - bin2hex((string) $header), - '504b0304' . // 4 bytes; Local file header signature - '2d00' . // 2 bytes; Version needed to extract (minimum) - '2222' . // 2 bytes; General purpose bit flag - '0800' . // 2 bytes; Compression method; e.g. none = 0, DEFLATE = 8 - '2008' . // 2 bytes; File last modification time - '2154' . // 2 bytes; File last modification date - '11111111' . // 4 bytes; CRC-32 of uncompressed data - '77777777' . // 4 bytes; Compressed size (or 0xffffffff for ZIP64) - '99999999' . // 4 bytes; Uncompressed size (or 0xffffffff for ZIP64) - '0800' . // 2 bytes; File name length (n) - '0c00' . // 2 bytes; Extra field length (m) - '746573742e706e67' . // n bytes; File name - '736f6d6520636f6e74656e74' // m bytes; Extra field - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/PackFieldTest.php b/vendor/maennchen/zipstream-php/test/PackFieldTest.php deleted file mode 100644 index ecd66bac7..000000000 --- a/vendor/maennchen/zipstream-php/test/PackFieldTest.php +++ /dev/null @@ -1,42 +0,0 @@ -assertSame( - bin2hex(PackField::pack(new PackField(format: 'v', value: 0x1122))), - '2211', - ); - } - - public function testOverflow2(): void - { - $this->expectException(RuntimeException::class); - - PackField::pack(new PackField(format: 'v', value: 0xFFFFF)); - } - - public function testOverflow4(): void - { - $this->expectException(RuntimeException::class); - - PackField::pack(new PackField(format: 'V', value: 0xFFFFFFFFF)); - } - - public function testUnknownOperator(): void - { - $this->assertSame( - bin2hex(PackField::pack(new PackField(format: 'a', value: 0x1122))), - '34', - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/ResourceStream.php b/vendor/maennchen/zipstream-php/test/ResourceStream.php deleted file mode 100644 index 8a414719a..000000000 --- a/vendor/maennchen/zipstream-php/test/ResourceStream.php +++ /dev/null @@ -1,160 +0,0 @@ -isSeekable()) { - $this->seek(0); - } - return (string) stream_get_contents($this->stream); - } - - public function close(): void - { - $stream = $this->detach(); - if ($stream) { - fclose($stream); - } - } - - public function detach() - { - $result = $this->stream; - // According to the interface, the stream is left in an unusable state; - /** @psalm-suppress PossiblyNullPropertyAssignmentValue */ - $this->stream = null; - return $result; - } - - public function seek(int $offset, int $whence = SEEK_SET): void - { - if (!$this->isSeekable()) { - throw new RuntimeException(); - } - if (fseek($this->stream, $offset, $whence) !== 0) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - } - - public function isSeekable(): bool - { - return (bool)$this->getMetadata('seekable'); - } - - public function getMetadata(?string $key = null) - { - $metadata = stream_get_meta_data($this->stream); - return $key !== null ? @$metadata[$key] : $metadata; - } - - public function getSize(): ?int - { - $stats = fstat($this->stream); - return $stats['size']; - } - - public function tell(): int - { - $position = ftell($this->stream); - if ($position === false) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - return $position; - } - - public function eof(): bool - { - return feof($this->stream); - } - - public function rewind(): void - { - $this->seek(0); - } - - public function write(string $string): int - { - if (!$this->isWritable()) { - throw new RuntimeException(); - } - if (fwrite($this->stream, $string) === false) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - return strlen($string); - } - - public function isWritable(): bool - { - $mode = $this->getMetadata('mode'); - if (!is_string($mode)) { - // @codeCoverageIgnoreStart - throw new RuntimeException('Could not get stream mode from metadata!'); - // @codeCoverageIgnoreEnd - } - return preg_match('/[waxc+]/', $mode) === 1; - } - - public function read(int $length): string - { - if (!$this->isReadable()) { - throw new RuntimeException(); - } - $result = fread($this->stream, $length); - if ($result === false) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - return $result; - } - - public function isReadable(): bool - { - $mode = $this->getMetadata('mode'); - if (!is_string($mode)) { - // @codeCoverageIgnoreStart - throw new RuntimeException('Could not get stream mode from metadata!'); - // @codeCoverageIgnoreEnd - } - return preg_match('/[r+]/', $mode) === 1; - } - - public function getContents(): string - { - if (!$this->isReadable()) { - throw new RuntimeException(); - } - $result = stream_get_contents($this->stream); - if ($result === false) { - // @codeCoverageIgnoreStart - throw new RuntimeException(); - // @codeCoverageIgnoreEnd - } - return $result; - } -} diff --git a/vendor/maennchen/zipstream-php/test/TimeTest.php b/vendor/maennchen/zipstream-php/test/TimeTest.php deleted file mode 100644 index 25aed277f..000000000 --- a/vendor/maennchen/zipstream-php/test/TimeTest.php +++ /dev/null @@ -1,35 +0,0 @@ -assertSame( - Time::dateTimeToDosTime(new DateTimeImmutable('2014-11-17T17:46:08Z')), - 1165069764 - ); - - // January 1 1980 - DOS Epoch. - $this->assertSame( - Time::dateTimeToDosTime(new DateTimeImmutable('1980-01-01T00:00:00+00:00')), - 2162688 - ); - } - - public function testTooEarlyDateToDosTime(): void - { - $this->expectException(DosTimeOverflowException::class); - - // January 1 1980 is the minimum DOS Epoch. - Time::dateTimeToDosTime(new DateTimeImmutable('1970-01-01T00:00:00+00:00')); - } -} diff --git a/vendor/maennchen/zipstream-php/test/Util.php b/vendor/maennchen/zipstream-php/test/Util.php deleted file mode 100644 index 4ec743e7c..000000000 --- a/vendor/maennchen/zipstream-php/test/Util.php +++ /dev/null @@ -1,135 +0,0 @@ -cmdExists('hexdump')) { - return ''; - } - - $output = []; - - if (!exec("hexdump -C \"$path\" | head -n 50", $output)) { - return ''; - } - - return "\nHexdump:\n" . implode("\n", $output); - } - - protected function validateAndExtractZip(string $zipPath): string - { - $tmpDir = $this->getTmpDir(); - - $zipArchive = new ZipArchive(); - $result = $zipArchive->open($zipPath); - - if ($result !== true) { - $codeName = $this->zipArchiveOpenErrorCodeName($result); - $debugInformation = $this->dumpZipContents($zipPath); - - $this->fail("Failed to open {$zipPath}. Code: $result ($codeName)$debugInformation"); - - return $tmpDir; - } - - $this->assertSame(0, $zipArchive->status); - $this->assertSame(0, $zipArchive->statusSys); - - $zipArchive->extractTo($tmpDir); - $zipArchive->close(); - - return $tmpDir; - } - - protected function zipArchiveOpenErrorCodeName(int $code): string - { - switch($code) { - case ZipArchive::ER_EXISTS: return 'ER_EXISTS'; - case ZipArchive::ER_INCONS: return 'ER_INCONS'; - case ZipArchive::ER_INVAL: return 'ER_INVAL'; - case ZipArchive::ER_MEMORY: return 'ER_MEMORY'; - case ZipArchive::ER_NOENT: return 'ER_NOENT'; - case ZipArchive::ER_NOZIP: return 'ER_NOZIP'; - case ZipArchive::ER_OPEN: return 'ER_OPEN'; - case ZipArchive::ER_READ: return 'ER_READ'; - case ZipArchive::ER_SEEK: return 'ER_SEEK'; - default: return 'unknown'; - } - } - - protected function getTmpDir(): string - { - $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); - unlink($tmp); - mkdir($tmp) or $this->fail('Failed to make directory'); - - return $tmp; - } - - /** - * @return string[] - */ - protected function getRecursiveFileList(string $path, bool $includeDirectories = false): array - { - $data = []; - $path = (string)realpath($path); - $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); - - $pathLen = strlen($path); - foreach ($files as $file) { - $filePath = $file->getRealPath(); - - if (is_dir($filePath) && !$includeDirectories) { - continue; - } - - $data[] = substr($filePath, $pathLen + 1); - } - - sort($data); - - return $data; - } -} diff --git a/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php b/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php deleted file mode 100644 index 49fb2ccb2..000000000 --- a/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -assertSame( - bin2hex($descriptor), - '504b0708' . // 4 bytes; Optional data descriptor signature = 0x08074b50 - '11111111' . // 4 bytes; CRC-32 of uncompressed data - '6666666677777777' . // 8 bytes; Compressed size - '8888888899999999' // 8 bytes; Uncompressed size - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php b/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php deleted file mode 100644 index 271a29862..000000000 --- a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -assertSame( - bin2hex($descriptor), - '504b0607' . // 4 bytes; zip64 end of central dir locator signature - 0x07064b50 - '11111111' . // 4 bytes; number of the disk with the start of the zip64 end of central directory - '3333333322222222' . // 28 bytes; relative offset of the zip64 end of central directory record - '44444444' // 4 bytes;total number of disks - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php b/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php deleted file mode 100644 index b86fb1781..000000000 --- a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php +++ /dev/null @@ -1,41 +0,0 @@ -assertSame( - bin2hex($descriptor), - '504b0606' . // 4 bytes;zip64 end of central dir signature - 0x06064b50 - '2f00000000000000' . // 8 bytes; size of zip64 end of central directory record - '3333' . // 2 bytes; version made by - '4444' . // 2 bytes; version needed to extract - '55555555' . // 4 bytes; number of this disk - '66666666' . // 4 bytes; number of the disk with the start of the central directory - '8888888877777777' . // 8 bytes; total number of entries in the central directory on this disk - 'aaaaaaaa99999999' . // 8 bytes; total number of entries in the central directory - 'ccccccccbbbbbbbb' . // 8 bytes; size of the central directory - 'eeeeeeeedddddddd' . // 8 bytes; offset of start of central directory with respect to the starting disk number - bin2hex('foo') - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php b/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php deleted file mode 100644 index 904783d86..000000000 --- a/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php +++ /dev/null @@ -1,42 +0,0 @@ -assertSame( - bin2hex($extraField), - '0100' . // 2 bytes; Tag for this "extra" block type - '1c00' . // 2 bytes; Size of this "extra" block - '6666666677777777' . // 8 bytes; Original uncompressed file size - '8888888899999999' . // 8 bytes; Size of compressed data - '1111111122222222' . // 8 bytes; Offset of local header record - '33333333' // 4 bytes; Number of the disk on which this file starts - ); - } - - public function testSerializesEmptyCorrectly(): void - { - $extraField = ExtendedInformationExtraField::generate(); - - $this->assertSame( - bin2hex($extraField), - '0100' . // 2 bytes; Tag for this "extra" block type - '0000' // 2 bytes; Size of this "extra" block - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/ZipStreamTest.php b/vendor/maennchen/zipstream-php/test/ZipStreamTest.php index 6e6902025..0aa65357d 100644 --- a/vendor/maennchen/zipstream-php/test/ZipStreamTest.php +++ b/vendor/maennchen/zipstream-php/test/ZipStreamTest.php @@ -2,42 +2,72 @@ declare(strict_types=1); -namespace ZipStream\Test; +namespace ZipStreamTest; -use DateTimeImmutable; use GuzzleHttp\Psr7\Response; -use GuzzleHttp\Psr7\StreamWrapper; use org\bovigo\vfs\vfsStream; use PHPUnit\Framework\TestCase; -use Psr\Http\Message\StreamInterface; -use RuntimeException; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use ReflectionClass; use ZipArchive; -use ZipStream\CompressionMethod; -use ZipStream\Exception\FileNotFoundException; -use ZipStream\Exception\FileNotReadableException; -use ZipStream\Exception\FileSizeIncorrectException; -use ZipStream\Exception\OverflowException; -use ZipStream\Exception\ResourceActionException; -use ZipStream\Exception\SimulationFileUnknownException; -use ZipStream\Exception\StreamNotReadableException; -use ZipStream\Exception\StreamNotSeekableException; -use ZipStream\OperationMode; -use ZipStream\PackField; +use ZipStream\File; +use ZipStream\Option\Archive as ArchiveOptions; +use ZipStream\Option\File as FileOptions; +use ZipStream\Option\Method; +use ZipStream\Stream; use ZipStream\ZipStream; +/** + * Test Class for the Main ZipStream CLass + */ class ZipStreamTest extends TestCase { - use Util; - use Assertions; + public function testFileNotFoundException(): void + { + $this->expectException(\ZipStream\Exception\FileNotFoundException::class); + // Get ZipStream Object + $zip = new ZipStream(); + + // Trigger error by adding a file which doesn't exist + $zip->addFileFromPath('foobar.php', '/foo/bar/foobar.php'); + } + + public function testFileNotReadableException(): void + { + // create new virtual filesystem + $root = vfsStream::setup('vfs'); + // create a virtual file with no permissions + $file = vfsStream::newFile('foo.txt', 0)->at($root)->setContent('bar'); + $zip = new ZipStream(); + $this->expectException(\ZipStream\Exception\FileNotReadableException::class); + $zip->addFileFromPath('foo.txt', $file->url()); + } + + public function testDostime(): void + { + // Allows testing of protected method + $class = new ReflectionClass(File::class); + $method = $class->getMethod('dostime'); + $method->setAccessible(true); + + $this->assertSame($method->invoke(null, 1416246368), 1165069764); + + // January 1 1980 - DOS Epoch. + $this->assertSame($method->invoke(null, 315532800), 2162688); + + // January 1 1970 -> January 1 1980 due to minimum DOS Epoch. @todo Throw Exception? + $this->assertSame($method->invoke(null, 0), 2162688); + } public function testAddFile(): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $zip->addFile('sample.txt', 'Sample String Data'); $zip->addFile('test/sample.txt', 'More Simple Sample Data'); @@ -58,10 +88,10 @@ class ZipStreamTest extends TestCase { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $name = 'árvíztűrő tükörfúrógép.txt'; $content = 'Sample String Data'; @@ -70,7 +100,10 @@ class ZipStreamTest extends TestCase 'from Hungarian language in lowercase. ' . 'In uppercase: ÁÍŰŐÜÖÚÓÉ'; - $zip->addFile(fileName: $name, data: $content, comment: $comment); + $fileOptions = new FileOptions(); + $fileOptions->setComment($comment); + + $zip->addFile($name, $content, $fileOptions); $zip->finish(); fclose($stream); @@ -80,19 +113,19 @@ class ZipStreamTest extends TestCase $this->assertSame([$name], $files); $this->assertStringEqualsFile($tmpDir . '/' . $name, $content); - $zipArchive = new ZipArchive(); - $zipArchive->open($tmp); - $this->assertSame($comment, $zipArchive->getCommentName($name)); + $zipArch = new ZipArchive(); + $zipArch->open($tmp); + $this->assertSame($comment, $zipArch->getCommentName($name)); } public function testAddFileUtf8NameNonUtfComment(): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $name = 'á.txt'; $content = 'any'; @@ -104,8 +137,10 @@ class ZipStreamTest extends TestCase // nearly CP850 (DOS-Latin-1) $guessComment = mb_convert_encoding($comment, 'UTF-8', 'CP850'); - $zip->addFile(fileName: $name, data: $content, comment: $comment); + $fileOptions = new FileOptions(); + $fileOptions->setComment($comment); + $zip->addFile($name, $content, $fileOptions); $zip->finish(); fclose($stream); @@ -115,49 +150,93 @@ class ZipStreamTest extends TestCase $this->assertSame($comment, $zipArch->getCommentName($name, ZipArchive::FL_ENC_RAW)); } + public function testAddFileNonUtf8NameUtfComment(): void + { + [$tmp, $stream] = $this->getTmpFileStream(); + + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $name = mb_convert_encoding('á.txt', 'ISO-8859-2', 'UTF-8'); + $content = 'any'; + $comment = 'á'; + + // @see https://libzip.org/documentation/zip_get_name.html + // + // mb_convert_encoding hasn't CP437. + // nearly CP850 (DOS-Latin-1) + $guessName = mb_convert_encoding($name, 'UTF-8', 'CP850'); + + $fileOptions = new FileOptions(); + $fileOptions->setComment($comment); + + $zip->addFile($name, $content, $fileOptions); + $zip->finish(); + fclose($stream); + + $tmpDir = $this->validateAndExtractZip($tmp); + + $files = $this->getRecursiveFileList($tmpDir); + + $this->assertNotSame([$name], $files); + $this->assertSame([$guessName], $files); + $this->assertStringEqualsFile($tmpDir . '/' . $guessName, $content); + + $zipArch = new ZipArchive(); + $zipArch->open($tmp); + $this->assertSame($guessName, $zipArch->getNameIndex(0)); + $this->assertSame($name, $zipArch->getNameIndex(0, ZipArchive::FL_ENC_RAW)); + $this->assertSame($comment, $zipArch->getCommentName($guessName)); + } + public function testAddFileWithStorageMethod(): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); - $zip->addFile(fileName: 'sample.txt', data: 'Sample String Data', compressionMethod: CompressionMethod::STORE); - $zip->addFile(fileName: 'test/sample.txt', data: 'More Simple Sample Data'); + $zip = new ZipStream(null, $options); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + $zip->addFile('sample.txt', 'Sample String Data', $fileOptions); + $zip->addFile('test/sample.txt', 'More Simple Sample Data'); $zip->finish(); fclose($stream); - $zipArchive = new ZipArchive(); - $zipArchive->open($tmp); + $zipArch = new ZipArchive(); + $zipArch->open($tmp); - $sample1 = $zipArchive->statName('sample.txt'); - $sample12 = $zipArchive->statName('test/sample.txt'); - $this->assertSame($sample1['comp_method'], CompressionMethod::STORE->value); - $this->assertSame($sample12['comp_method'], CompressionMethod::DEFLATE->value); + $sample1 = $zipArch->statName('sample.txt'); + $sample12 = $zipArch->statName('test/sample.txt'); + $this->assertSame($sample1['comp_method'], Method::STORE); + $this->assertSame($sample12['comp_method'], Method::DEFLATE); - $zipArchive->close(); + $zipArch->close(); } public function testAddFileFromPath(): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); [$tmpExample, $streamExample] = $this->getTmpFileStream(); fwrite($streamExample, 'Sample String Data'); fclose($streamExample); - $zip->addFileFromPath(fileName: 'sample.txt', path: $tmpExample); + $zip->addFileFromPath('sample.txt', $tmpExample); [$tmpExample, $streamExample] = $this->getTmpFileStream(); fwrite($streamExample, 'More Simple Sample Data'); fclose($streamExample); - $zip->addFileFromPath(fileName: 'test/sample.txt', path: $tmpExample); + $zip->addFileFromPath('test/sample.txt', $tmpExample); $zip->finish(); fclose($stream); @@ -171,57 +250,22 @@ class ZipStreamTest extends TestCase $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); } - public function testAddFileFromPathFileNotFoundException(): void - { - $this->expectException(FileNotFoundException::class); - - [, $stream] = $this->getTmpFileStream(); - - // Get ZipStream Object - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); - - // Trigger error by adding a file which doesn't exist - $zip->addFileFromPath(fileName: 'foobar.php', path: '/foo/bar/foobar.php'); - } - - public function testAddFileFromPathFileNotReadableException(): void - { - $this->expectException(FileNotReadableException::class); - - - [, $stream] = $this->getTmpFileStream(); - - - // create new virtual filesystem - $root = vfsStream::setup('vfs'); - // create a virtual file with no permissions - $file = vfsStream::newFile('foo.txt', 0)->at($root)->setContent('bar'); - - // Get ZipStream Object - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); - - $zip->addFileFromPath('foo.txt', $file->url()); - } - public function testAddFileFromPathWithStorageMethod(): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); [$tmpExample, $streamExample] = $this->getTmpFileStream(); fwrite($streamExample, 'Sample String Data'); fclose($streamExample); - $zip->addFileFromPath(fileName: 'sample.txt', path: $tmpExample, compressionMethod: CompressionMethod::STORE); + $zip->addFileFromPath('sample.txt', $tmpExample, $fileOptions); [$tmpExample, $streamExample] = $this->getTmpFileStream(); fwrite($streamExample, 'More Simple Sample Data'); @@ -231,31 +275,29 @@ class ZipStreamTest extends TestCase $zip->finish(); fclose($stream); - $zipArchive = new ZipArchive(); - $zipArchive->open($tmp); + $zipArch = new ZipArchive(); + $zipArch->open($tmp); - $sample1 = $zipArchive->statName('sample.txt'); - $this->assertSame(CompressionMethod::STORE->value, $sample1['comp_method']); + $sample1 = $zipArch->statName('sample.txt'); + $this->assertSame(Method::STORE, $sample1['comp_method']); - $sample2 = $zipArchive->statName('test/sample.txt'); - $this->assertSame(CompressionMethod::DEFLATE->value, $sample2['comp_method']); + $sample2 = $zipArch->statName('test/sample.txt'); + $this->assertSame(Method::DEFLATE, $sample2['comp_method']); - $zipArchive->close(); + $zipArch->close(); } public function testAddLargeFileFromPath(): void { - foreach ([CompressionMethod::DEFLATE, CompressionMethod::STORE] as $compressionMethod) { - foreach ([false, true] as $zeroHeader) { - foreach ([false, true] as $zip64) { - if ($zeroHeader && $compressionMethod === CompressionMethod::DEFLATE) { + $methods = [Method::DEFLATE(), Method::STORE()]; + $falseTrue = [false, true]; + foreach ($methods as $method) { + foreach ($falseTrue as $zeroHeader) { + foreach ($falseTrue as $zip64) { + if ($zeroHeader && $method->equals(Method::DEFLATE())) { continue; } - $this->addLargeFileFileFromPath( - compressionMethod: $compressionMethod, - zeroHeader: $zeroHeader, - zip64: $zip64 - ); + $this->addLargeFileFileFromPath($method, $zeroHeader, $zip64); } } } @@ -265,23 +307,26 @@ class ZipStreamTest extends TestCase { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); // In this test we can't use temporary stream to feed data // because zlib.deflate filter gives empty string before PHP 7 // it works fine with file stream $streamExample = fopen(__FILE__, 'rb'); $zip->addFileFromStream('sample.txt', $streamExample); - fclose($streamExample); +// fclose($streamExample); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); $streamExample2 = fopen('php://temp', 'wb+'); fwrite($streamExample2, 'More Simple Sample Data'); rewind($streamExample2); // move the pointer back to the beginning of file. - $zip->addFileFromStream('test/sample.txt', $streamExample2); //, $fileOptions); - fclose($streamExample2); + $zip->addFileFromStream('test/sample.txt', $streamExample2, $fileOptions); +// fclose($streamExample2); $zip->finish(); fclose($stream); @@ -295,162 +340,61 @@ class ZipStreamTest extends TestCase $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data'); } - public function testAddFileFromStreamUnreadableInput(): void - { - $this->expectException(StreamNotReadableException::class); - - [, $stream] = $this->getTmpFileStream(); - [$tmpInput] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); - - $streamUnreadable = fopen($tmpInput, 'w'); - - $zip->addFileFromStream('sample.json', $streamUnreadable); - } - - public function testAddFileFromStreamBrokenOutputWrite(): void - { - $this->expectException(ResourceActionException::class); - - $outputStream = FaultInjectionResource::getResource(['stream_write']); - - $zip = new ZipStream( - outputStream: $outputStream, - sendHttpHeaders: false, - ); - - $zip->addFile('sample.txt', 'foobar'); - } - - public function testAddFileFromStreamBrokenInputRewind(): void - { - $this->expectException(ResourceActionException::class); - - [,$stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - defaultEnableZeroHeader: false, - ); - - $fileStream = FaultInjectionResource::getResource(['stream_seek']); - - $zip->addFileFromStream('sample.txt', $fileStream, maxSize: 0); - } - - public function testAddFileFromStreamUnseekableInputWithoutZeroHeader(): void - { - $this->expectException(StreamNotSeekableException::class); - - [, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - defaultEnableZeroHeader: false, - ); - - if (file_exists('/dev/null')) { - $streamUnseekable = fopen('/dev/null', 'w+'); - } elseif (file_exists('NUL')) { - $streamUnseekable = fopen('NUL', 'w+'); - } else { - $this->markTestSkipped('Needs file /dev/null'); - } - - $zip->addFileFromStream('sample.txt', $streamUnseekable, maxSize: 2); - } - - public function testAddFileFromStreamUnseekableInputWithZeroHeader(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - defaultEnableZeroHeader: true, - defaultCompressionMethod: CompressionMethod::STORE, - ); - - $streamUnseekable = StreamWrapper::getResource(new class ('test') extends EndlessCycleStream { - public function isSeekable(): bool - { - return false; - } - - public function seek(int $offset, int $whence = SEEK_SET): void - { - throw new RuntimeException('Not seekable'); - } - }); - - $zip->addFileFromStream('sample.txt', $streamUnseekable, maxSize: 7); - - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.txt'], $files); - - $this->assertSame(filesize($tmpDir . '/sample.txt'), 7); - } - public function testAddFileFromStreamWithStorageMethod(): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); + + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); $streamExample = fopen('php://temp', 'wb+'); fwrite($streamExample, 'Sample String Data'); rewind($streamExample); // move the pointer back to the beginning of file. - $zip->addFileFromStream('sample.txt', $streamExample, compressionMethod: CompressionMethod::STORE); - fclose($streamExample); + $zip->addFileFromStream('sample.txt', $streamExample, $fileOptions); +// fclose($streamExample); $streamExample2 = fopen('php://temp', 'bw+'); fwrite($streamExample2, 'More Simple Sample Data'); rewind($streamExample2); // move the pointer back to the beginning of file. - $zip->addFileFromStream('test/sample.txt', $streamExample2, compressionMethod: CompressionMethod::DEFLATE); - fclose($streamExample2); + $zip->addFileFromStream('test/sample.txt', $streamExample2); +// fclose($streamExample2); $zip->finish(); fclose($stream); - $zipArchive = new ZipArchive(); - $zipArchive->open($tmp); + $zipArch = new ZipArchive(); + $zipArch->open($tmp); - $sample1 = $zipArchive->statName('sample.txt'); - $this->assertSame(CompressionMethod::STORE->value, $sample1['comp_method']); + $sample1 = $zipArch->statName('sample.txt'); + $this->assertSame(Method::STORE, $sample1['comp_method']); - $sample2 = $zipArchive->statName('test/sample.txt'); - $this->assertSame(CompressionMethod::DEFLATE->value, $sample2['comp_method']); + $sample2 = $zipArch->statName('test/sample.txt'); + $this->assertSame(Method::DEFLATE, $sample2['comp_method']); - $zipArchive->close(); + $zipArch->close(); } public function testAddFileFromPsr7Stream(): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $body = 'Sample String Data'; $response = new Response(200, [], $body); - $zip->addFileFromPsr7Stream('sample.json', $response->getBody()); + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); $zip->finish(); fclose($stream); @@ -461,295 +405,23 @@ class ZipStreamTest extends TestCase $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); } - /** - * @group slow - */ - public function testAddLargeFileFromPsr7Stream(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - enableZip64: true, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x100000000, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.json'], $files); - $this->assertFileIsReadable($tmpDir . '/sample.json'); - $this->assertStringStartsWith('000000', file_get_contents(filename: $tmpDir . '/sample.json', length: 20)); - } - - public function testContinueFinishedZip(): void - { - $this->expectException(RuntimeException::class); - - [, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); - $zip->finish(); - - $zip->addFile('sample.txt', '1234'); - } - - /** - * @group slow - */ - public function testManyFilesWithoutZip64(): void - { - $this->expectException(OverflowException::class); - - [, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - enableZip64: false, - ); - - for ($i = 0; $i <= 0xFFFF; $i++) { - $zip->addFile('sample' . $i, ''); - } - - $zip->finish(); - } - - /** - * @group slow - */ - public function testManyFilesWithZip64(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - enableZip64: true, - ); - - for ($i = 0; $i <= 0xFFFF; $i++) { - $zip->addFile('sample' . $i, ''); - } - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - - $this->assertSame(count($files), 0x10000); - } - - /** - * @group slow - */ - public function testLongZipWithout64(): void - { - $this->expectException(OverflowException::class); - - [, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - enableZip64: false, - defaultCompressionMethod: CompressionMethod::STORE, - ); - - for ($i = 0; $i < 4; $i++) { - $zip->addFileFromPsr7Stream( - fileName: 'sample' . $i, - stream: new EndlessCycleStream('0'), - maxSize: 0xFFFFFFFF, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - } - } - - /** - * @group slow - */ - public function testLongZipWith64(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - enableZip64: true, - defaultCompressionMethod: CompressionMethod::STORE, - ); - - for ($i = 0; $i < 4; $i++) { - $zip->addFileFromPsr7Stream( - fileName: 'sample' . $i, - stream: new EndlessCycleStream('0'), - maxSize: 0x5FFFFFFF, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - } - - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample0', 'sample1', 'sample2', 'sample3'], $files); - } - - /** - * @group slow - */ - public function testAddLargeFileWithoutZip64WithZeroHeader(): void - { - $this->expectException(OverflowException::class); - - [, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - enableZip64: false, - defaultEnableZeroHeader: true, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x100000000, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - } - - /** - * @group slow - */ - public function testAddsZip64HeaderWhenNeeded(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - enableZip64: true, - defaultEnableZeroHeader: false, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x100000000, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($tmp); - $files = $this->getRecursiveFileList($tmpDir); - - $this->assertSame(['sample.json'], $files); - $this->assertFileContains($tmp, PackField::pack( - new PackField(format: 'V', value: 0x06064b50) - )); - } - - /** - * @group slow - */ - public function testDoesNotAddZip64HeaderWhenNotNeeded(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - enableZip64: true, - defaultEnableZeroHeader: false, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x10, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - - $zip->finish(); - - $tmpDir = $this->validateAndExtractZip($tmp); - $files = $this->getRecursiveFileList($tmpDir); - - $this->assertSame(['sample.json'], $files); - $this->assertFileDoesNotContain($tmp, PackField::pack( - new PackField(format: 'V', value: 0x06064b50) - )); - } - - /** - * @group slow - */ - public function testAddLargeFileWithoutZip64WithoutZeroHeader(): void - { - $this->expectException(OverflowException::class); - - [, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - enableZip64: false, - defaultEnableZeroHeader: false, - ); - - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: new EndlessCycleStream('0'), - maxSize: 0x100000000, - compressionMethod: CompressionMethod::STORE, - lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'), - ); - } - public function testAddFileFromPsr7StreamWithOutputToPsr7Stream(): void { [$tmp, $resource] = $this->getTmpFileStream(); - $psr7OutputStream = new ResourceStream($resource); + $psr7OutputStream = new Stream($resource); + $options = new ArchiveOptions(); + $options->setOutputStream($psr7OutputStream); - $zip = new ZipStream( - outputStream: $psr7OutputStream, - sendHttpHeaders: false, - ); + $zip = new ZipStream(null, $options); $body = 'Sample String Data'; $response = new Response(200, [], $body); - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: $response->getBody(), - compressionMethod: CompressionMethod::STORE, - ); + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + + $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); $zip->finish(); $psr7OutputStream->close(); @@ -764,10 +436,10 @@ class ZipStreamTest extends TestCase { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + + $zip = new ZipStream(null, $options); $body = 'Sample String Data'; $fileSize = strlen($body); @@ -775,12 +447,10 @@ class ZipStreamTest extends TestCase $fakePadding = "\0\0\0\0\0\0"; $response = new Response(200, [], $body . $fakePadding); - $zip->addFileFromPsr7Stream( - fileName: 'sample.json', - stream: $response->getBody(), - compressionMethod: CompressionMethod::STORE, - maxSize: $fileSize - ); + $fileOptions = new FileOptions(); + $fileOptions->setMethod(Method::STORE()); + $fileOptions->setSize($fileSize); + $zip->addFileFromPsr7Stream('sample.json', $response->getBody(), $fileOptions); $zip->finish(); fclose($stream); @@ -791,46 +461,15 @@ class ZipStreamTest extends TestCase $this->assertStringEqualsFile($tmpDir . '/sample.json', $body); } - public function testCreateArchiveHeaders(): void - { - [, $stream] = $this->getTmpFileStream(); - - $headers = []; - - $httpHeaderCallback = function (string $header) use (&$headers) { - $headers[] = $header; - }; - - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: true, - outputName: 'example.zip', - httpHeaderCallback: $httpHeaderCallback, - ); - - $zip->addFile( - fileName: 'sample.json', - data: 'foo', - ); - $zip->finish(); - fclose($stream); - - $this->assertContains('Content-Type: application/x-zip', $headers); - $this->assertContains("Content-Disposition: attachment; filename*=UTF-8''example.zip", $headers); - $this->assertContains('Pragma: public', $headers); - $this->assertContains('Cache-Control: public, must-revalidate', $headers); - $this->assertContains('Content-Transfer-Encoding: binary', $headers); - } - public function testCreateArchiveWithFlushOptionSet(): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - flushOutput: true, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + $options->setFlushOutput(true); + + $zip = new ZipStream(null, $options); $zip->addFile('sample.txt', 'Sample String Data'); $zip->addFile('test/sample.txt', 'More Simple Sample Data'); @@ -855,11 +494,11 @@ class ZipStreamTest extends TestCase [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - flushOutput: true, - sendHttpHeaders: false, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + $options->setFlushOutput(true); + + $zip = new ZipStream(null, $options); $zip->addFile('sample.txt', 'Sample String Data'); @@ -873,391 +512,87 @@ class ZipStreamTest extends TestCase ob_start(); } - public function testAddEmptyDirectory(): void + /** + * @return array + */ + protected function getTmpFileStream(): array { - [$tmp, $stream] = $this->getTmpFileStream(); + $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); + $stream = fopen($tmp, 'wb+'); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - ); - - $zip->addDirectory('foo'); - - $zip->finish(); - fclose($stream); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir, includeDirectories: true); - - $this->assertContains('foo', $files); - - $this->assertFileExists($tmpDir . DIRECTORY_SEPARATOR . 'foo'); - $this->assertDirectoryExists($tmpDir . DIRECTORY_SEPARATOR . 'foo'); + return [$tmp, $stream]; } - public function testAddFileSimulate(): void + /** + * @param string $tmp + * @return string + */ + protected function validateAndExtractZip($tmp): string { - [, $stream] = $this->getTmpFileStream(); + $tmpDir = $this->getTmpDir(); - $create = function (OperationMode $operationMode) use ($stream): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultEnableZeroHeader: true, - outputStream: $stream, - ); + $zipArch = new ZipArchive(); + $res = $zipArch->open($tmp); - $zip->addFile('sample.txt', 'Sample String Data'); - $zip->addFile('test/sample.txt', 'More Simple Sample Data'); + if ($res !== true) { + $this->fail("Failed to open {$tmp}. Code: $res"); - return $zip->finish(); - }; + return $tmpDir; + } + $this->assertSame(0, $zipArch->status); + $this->assertSame(0, $zipArch->statusSys); - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); + $zipArch->extractTo($tmpDir); + $zipArch->close(); - $this->assertEquals($sizeExpected, $sizeActual); + return $tmpDir; } - public function testAddFileSimulateWithMaxSize(): void + protected function getTmpDir(): string { - [, $stream] = $this->getTmpFileStream(); + $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest'); + unlink($tmp); + mkdir($tmp) or $this->fail('Failed to make directory'); - $create = function (OperationMode $operationMode) use ($stream): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: true, - outputStream: $stream, - ); - - $zip->addFile('sample.txt', 'Sample String Data', maxSize: 0); - - return $zip->finish(); - }; - - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - $this->assertEquals($sizeExpected, $sizeActual); + return $tmp; } - public function testAddFileSimulateWithFstat(): void + /** + * @param string $path + * @return string[] + */ + protected function getRecursiveFileList(string $path): array { - [, $stream] = $this->getTmpFileStream(); + $data = []; + $path = (string)realpath($path); + $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); - $create = function (OperationMode $operationMode) use ($stream): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: true, - outputStream: $stream, - ); - - $zip->addFile('sample.txt', 'Sample String Data'); - $zip->addFile('test/sample.txt', 'More Simple Sample Data'); - - return $zip->finish(); - }; - - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - $this->assertEquals($sizeExpected, $sizeActual); - } - - public function testAddFileSimulateWithExactSizeZero(): void - { - [, $stream] = $this->getTmpFileStream(); - - $create = function (OperationMode $operationMode) use ($stream): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: true, - outputStream: $stream, - ); - - $zip->addFile('sample.txt', 'Sample String Data', exactSize: 18); - - return $zip->finish(); - }; - - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - $this->assertEquals($sizeExpected, $sizeActual); - } - - public function testAddFileSimulateWithExactSizeInitial(): void - { - [, $stream] = $this->getTmpFileStream(); - - $create = function (OperationMode $operationMode) use ($stream): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: false, - outputStream: $stream, - ); - - $zip->addFile('sample.txt', 'Sample String Data', exactSize: 18); - - return $zip->finish(); - }; - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - $this->assertEquals($sizeExpected, $sizeActual); - } - - public function testAddFileSimulateWithZeroSizeInFstat(): void - { - [, $stream] = $this->getTmpFileStream(); - - $create = function (OperationMode $operationMode) use ($stream): int { - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: $operationMode, - defaultCompressionMethod: CompressionMethod::STORE, - defaultEnableZeroHeader: false, - outputStream: $stream, - ); - - $zip->addFileFromPsr7Stream('sample.txt', new class () implements StreamInterface { - public $pos = 0; - - public function __toString(): string - { - return 'test'; - } - - public function close(): void - { - } - - public function detach() - { - } - - public function getSize(): ?int - { - return null; - } - - public function tell(): int - { - return $this->pos; - } - - public function eof(): bool - { - return $this->pos >= 4; - } - - public function isSeekable(): bool - { - return true; - } - - public function seek(int $offset, int $whence = SEEK_SET): void - { - $this->pos = $offset; - } - - public function rewind(): void - { - $this->pos = 0; - } - - public function isWritable(): bool - { - return false; - } - - public function write(string $string): int - { - return 0; - } - - public function isReadable(): bool - { - return true; - } - - public function read(int $length): string - { - $data = substr('test', $this->pos, $length); - $this->pos += strlen($data); - return $data; - } - - public function getContents(): string - { - return $this->read(4); - } - - public function getMetadata(?string $key = null) - { - return $key !== null ? null : []; - } - }); - - return $zip->finish(); - }; - - $sizeExpected = $create(OperationMode::NORMAL); - $sizeActual = $create(OperationMode::SIMULATE_LAX); - - - $this->assertEquals($sizeExpected, $sizeActual); - } - - public function testAddFileSimulateWithWrongExactSize(): void - { - $this->expectException(FileSizeIncorrectException::class); - - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: OperationMode::SIMULATE_LAX, - ); - - $zip->addFile('sample.txt', 'Sample String Data', exactSize: 1000); - } - - public function testAddFileSimulateStrictZero(): void - { - $this->expectException(SimulationFileUnknownException::class); - - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: OperationMode::SIMULATE_STRICT, - defaultEnableZeroHeader: true - ); - - $zip->addFile('sample.txt', 'Sample String Data'); - } - - public function testAddFileSimulateStrictInitial(): void - { - $this->expectException(SimulationFileUnknownException::class); - - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: OperationMode::SIMULATE_STRICT, - defaultEnableZeroHeader: false - ); - - $zip->addFile('sample.txt', 'Sample String Data'); - } - - public function testAddFileCallbackStrict(): void - { - $this->expectException(SimulationFileUnknownException::class); - - $zip = new ZipStream( - sendHttpHeaders: false, - operationMode: OperationMode::SIMULATE_STRICT, - defaultEnableZeroHeader: false - ); - - $zip->addFileFromCallback('sample.txt', callback: function () { - return ''; - }); - } - - public function testAddFileCallbackLax(): void - { - - $zip = new ZipStream( - operationMode: OperationMode::SIMULATE_LAX, - defaultEnableZeroHeader: false, - sendHttpHeaders: false, - ); - - $zip->addFileFromCallback('sample.txt', callback: function () { - return 'Sample String Data'; - }); - - $size = $zip->finish(); - - $this->assertEquals($size, 142); - } - - public function testExecuteSimulation(): void - { - [$tmp, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - operationMode: OperationMode::SIMULATE_LAX, - defaultEnableZeroHeader: false, - sendHttpHeaders: false, - outputStream: $stream, - ); - - $zip->addFileFromCallback( - 'sample.txt', - exactSize: 18, - callback: function () { - return 'Sample String Data'; + $pathLen = strlen($path); + foreach ($files as $file) { + $filePath = $file->getRealPath(); + if (!is_dir($filePath)) { + $data[] = substr($filePath, $pathLen + 1); } - ); + } - $size = $zip->finish(); + sort($data); - $this->assertEquals(filesize($tmp), 0); - - $zip->executeSimulation(); - fclose($stream); - - clearstatcache(); - - $this->assertEquals(filesize($tmp), $size); - - $tmpDir = $this->validateAndExtractZip($tmp); - - $files = $this->getRecursiveFileList($tmpDir); - $this->assertSame(['sample.txt'], $files); + return $data; } - public function testExecuteSimulationBeforeFinish(): void - { - $this->expectException(RuntimeException::class); - - - [, $stream] = $this->getTmpFileStream(); - - $zip = new ZipStream( - operationMode: OperationMode::SIMULATE_LAX, - defaultEnableZeroHeader: false, - sendHttpHeaders: false, - outputStream: $stream, - ); - - $zip->executeSimulation(); - } - - private function addLargeFileFileFromPath(CompressionMethod $compressionMethod, $zeroHeader, $zip64): void + protected function addLargeFileFileFromPath($method, $zeroHeader, $zip64): void { [$tmp, $stream] = $this->getTmpFileStream(); - $zip = new ZipStream( - outputStream: $stream, - sendHttpHeaders: false, - defaultEnableZeroHeader: $zeroHeader, - enableZip64: $zip64, - ); + $options = new ArchiveOptions(); + $options->setOutputStream($stream); + $options->setLargeFileMethod($method); + $options->setLargeFileSize(5); + $options->setZeroHeader($zeroHeader); + $options->setEnableZip64($zip64); + + $zip = new ZipStream(null, $options); [$tmpExample, $streamExample] = $this->getTmpFileStream(); for ($i = 0; $i <= 10000; $i++) { @@ -1279,6 +614,6 @@ class ZipStreamTest extends TestCase $files = $this->getRecursiveFileList($tmpDir); $this->assertSame(['sample.txt'], $files); - $this->assertSame(sha1_file($tmpDir . '/sample.txt'), $shaExample, "SHA-1 Mismatch Method: {$compressionMethod->value}"); + $this->assertSame(sha1_file($tmpDir . '/sample.txt'), $shaExample, "SHA-1 Mismatch Method: {$method}"); } } diff --git a/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php b/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php deleted file mode 100644 index 2b8dbed4a..000000000 --- a/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php +++ /dev/null @@ -1,22 +0,0 @@ -assertSame( - bin2hex((string) $extraField), - '5356' . // 2 bytes; Tag for this "extra" block type - '0000' // 2 bytes; TODO: Document - ); - } -} diff --git a/vendor/maennchen/zipstream-php/test/bug/BugHonorFileTimeTest.php b/vendor/maennchen/zipstream-php/test/bug/BugHonorFileTimeTest.php new file mode 100644 index 000000000..05de4fe26 --- /dev/null +++ b/vendor/maennchen/zipstream-php/test/bug/BugHonorFileTimeTest.php @@ -0,0 +1,40 @@ +setOutputStream(fopen('php://memory', 'wb')); + $fileOpt->setTime(clone $expectedTime); + + $zip = new ZipStream(null, $archiveOpt); + + $zip->addFile('sample.txt', 'Sample', $fileOpt); + + $zip->finish(); + + $this->assertEquals($expectedTime, $fileOpt->getTime()); + } +} diff --git a/vendor/myclabs/php-enum/LICENSE b/vendor/myclabs/php-enum/LICENSE new file mode 100644 index 000000000..2a8cf22ec --- /dev/null +++ b/vendor/myclabs/php-enum/LICENSE @@ -0,0 +1,18 @@ +The MIT License (MIT) + +Copyright (c) 2015 My C-Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/myclabs/php-enum/README.md b/vendor/myclabs/php-enum/README.md new file mode 100644 index 000000000..1e4d1ff42 --- /dev/null +++ b/vendor/myclabs/php-enum/README.md @@ -0,0 +1,138 @@ +# PHP Enum implementation inspired from SplEnum + +[![Build Status](https://travis-ci.org/myclabs/php-enum.png?branch=master)](https://travis-ci.org/myclabs/php-enum) +[![Latest Stable Version](https://poser.pugx.org/myclabs/php-enum/version.png)](https://packagist.org/packages/myclabs/php-enum) +[![Total Downloads](https://poser.pugx.org/myclabs/php-enum/downloads.png)](https://packagist.org/packages/myclabs/php-enum) +[![psalm](https://shepherd.dev/github/myclabs/php-enum/coverage.svg)](https://shepherd.dev/github/myclabs/php-enum) + +Maintenance for this project is [supported via Tidelift](https://tidelift.com/subscription/pkg/packagist-myclabs-php-enum?utm_source=packagist-myclabs-php-enum&utm_medium=referral&utm_campaign=readme). + +## Why? + +First, and mainly, `SplEnum` is not integrated to PHP, you have to install the extension separately. + +Using an enum instead of class constants provides the following advantages: + +- You can use an enum as a parameter type: `function setAction(Action $action) {` +- You can use an enum as a return type: `function getAction() : Action {` +- You can enrich the enum with methods (e.g. `format`, `parse`, …) +- You can extend the enum to add new values (make your enum `final` to prevent it) +- You can get a list of all the possible values (see below) + +This Enum class is not intended to replace class constants, but only to be used when it makes sense. + +## Installation + +``` +composer require myclabs/php-enum +``` + +## Declaration + +```php +use MyCLabs\Enum\Enum; + +/** + * Action enum + */ +final class Action extends Enum +{ + private const VIEW = 'view'; + private const EDIT = 'edit'; +} +``` + +## Usage + +```php +$action = Action::VIEW(); + +// or with a dynamic key: +$action = Action::$key(); +// or with a dynamic value: +$action = Action::from($value); +// or +$action = new Action($value); +``` + +As you can see, static methods are automatically implemented to provide quick access to an enum value. + +One advantage over using class constants is to be able to use an enum as a parameter type: + +```php +function setAction(Action $action) { + // ... +} +``` + +## Documentation + +- `__construct()` The constructor checks that the value exist in the enum +- `__toString()` You can `echo $myValue`, it will display the enum value (value of the constant) +- `getValue()` Returns the current value of the enum +- `getKey()` Returns the key of the current value on Enum +- `equals()` Tests whether enum instances are equal (returns `true` if enum values are equal, `false` otherwise) + +Static methods: + +- `from()` Creates an Enum instance, checking that the value exist in the enum +- `toArray()` method Returns all possible values as an array (constant name in key, constant value in value) +- `keys()` Returns the names (keys) of all constants in the Enum class +- `values()` Returns instances of the Enum class of all Enum constants (constant name in key, Enum instance in value) +- `isValid()` Check if tested value is valid on enum set +- `isValidKey()` Check if tested key is valid on enum set +- `assertValidValue()` Assert the value is valid on enum set, throwing exception otherwise +- `search()` Return key for searched value + +### Static methods + +```php +final class Action extends Enum +{ + private const VIEW = 'view'; + private const EDIT = 'edit'; +} + +// Static method: +$action = Action::VIEW(); +$action = Action::EDIT(); +``` + +Static method helpers are implemented using [`__callStatic()`](http://www.php.net/manual/en/language.oop5.overloading.php#object.callstatic). + +If you care about IDE autocompletion, you can either implement the static methods yourself: + +```php +final class Action extends Enum +{ + private const VIEW = 'view'; + + /** + * @return Action + */ + public static function VIEW() { + return new Action(self::VIEW); + } +} +``` + +or you can use phpdoc (this is supported in PhpStorm for example): + +```php +/** + * @method static Action VIEW() + * @method static Action EDIT() + */ +final class Action extends Enum +{ + private const VIEW = 'view'; + private const EDIT = 'edit'; +} +``` + +## Related projects + +- [Doctrine enum mapping](https://github.com/acelaya/doctrine-enum-type) +- [Symfony ParamConverter integration](https://github.com/Ex3v/MyCLabsEnumParamConverter) +- [PHPStan integration](https://github.com/timeweb/phpstan-enum) +- [Yii2 enum mapping](https://github.com/KartaviK/yii2-enum) diff --git a/vendor/myclabs/php-enum/SECURITY.md b/vendor/myclabs/php-enum/SECURITY.md new file mode 100644 index 000000000..84fd4e320 --- /dev/null +++ b/vendor/myclabs/php-enum/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +## Supported Versions + +Only the latest stable release is supported. + +## Reporting a Vulnerability + +To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). + +Tidelift will coordinate the fix and disclosure. diff --git a/vendor/myclabs/php-enum/composer.json b/vendor/myclabs/php-enum/composer.json new file mode 100644 index 000000000..924f924bb --- /dev/null +++ b/vendor/myclabs/php-enum/composer.json @@ -0,0 +1,33 @@ +{ + "name": "myclabs/php-enum", + "type": "library", + "description": "PHP Enum implementation", + "keywords": ["enum"], + "homepage": "http://github.com/myclabs/php-enum", + "license": "MIT", + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "MyCLabs\\Tests\\Enum\\": "tests/" + } + }, + "require": { + "php": "^7.3 || ^8.0", + "ext-json": "*" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.6.2" + } +} diff --git a/vendor/myclabs/php-enum/psalm.xml b/vendor/myclabs/php-enum/psalm.xml new file mode 100644 index 000000000..ff06b66ed --- /dev/null +++ b/vendor/myclabs/php-enum/psalm.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/myclabs/php-enum/src/Enum.php b/vendor/myclabs/php-enum/src/Enum.php new file mode 100644 index 000000000..89064eba7 --- /dev/null +++ b/vendor/myclabs/php-enum/src/Enum.php @@ -0,0 +1,318 @@ + + * @author Daniel Costa + * @author Mirosław Filip + * + * @psalm-template T + * @psalm-immutable + * @psalm-consistent-constructor + */ +abstract class Enum implements \JsonSerializable +{ + /** + * Enum value + * + * @var mixed + * @psalm-var T + */ + protected $value; + + /** + * Enum key, the constant name + * + * @var string + */ + private $key; + + /** + * Store existing constants in a static cache per object. + * + * + * @var array + * @psalm-var array> + */ + protected static $cache = []; + + /** + * Cache of instances of the Enum class + * + * @var array + * @psalm-var array> + */ + protected static $instances = []; + + /** + * Creates a new value of some type + * + * @psalm-pure + * @param mixed $value + * + * @psalm-param T $value + * @throws \UnexpectedValueException if incompatible type is given. + */ + public function __construct($value) + { + if ($value instanceof static) { + /** @psalm-var T */ + $value = $value->getValue(); + } + + /** @psalm-suppress ImplicitToStringCast assertValidValueReturningKey returns always a string but psalm has currently an issue here */ + $this->key = static::assertValidValueReturningKey($value); + + /** @psalm-var T */ + $this->value = $value; + } + + /** + * This method exists only for the compatibility reason when deserializing a previously serialized version + * that didn't had the key property + */ + public function __wakeup() + { + /** @psalm-suppress DocblockTypeContradiction key can be null when deserializing an enum without the key */ + if ($this->key === null) { + /** + * @psalm-suppress InaccessibleProperty key is not readonly as marked by psalm + * @psalm-suppress PossiblyFalsePropertyAssignmentValue deserializing a case that was removed + */ + $this->key = static::search($this->value); + } + } + + /** + * @param mixed $value + * @return static + */ + public static function from($value): self + { + $key = static::assertValidValueReturningKey($value); + + return self::__callStatic($key, []); + } + + /** + * @psalm-pure + * @return mixed + * @psalm-return T + */ + public function getValue() + { + return $this->value; + } + + /** + * Returns the enum key (i.e. the constant name). + * + * @psalm-pure + * @return string + */ + public function getKey() + { + return $this->key; + } + + /** + * @psalm-pure + * @psalm-suppress InvalidCast + * @return string + */ + public function __toString() + { + return (string)$this->value; + } + + /** + * Determines if Enum should be considered equal with the variable passed as a parameter. + * Returns false if an argument is an object of different class or not an object. + * + * This method is final, for more information read https://github.com/myclabs/php-enum/issues/4 + * + * @psalm-pure + * @psalm-param mixed $variable + * @return bool + */ + final public function equals($variable = null): bool + { + return $variable instanceof self + && $this->getValue() === $variable->getValue() + && static::class === \get_class($variable); + } + + /** + * Returns the names (keys) of all constants in the Enum class + * + * @psalm-pure + * @psalm-return list + * @return array + */ + public static function keys() + { + return \array_keys(static::toArray()); + } + + /** + * Returns instances of the Enum class of all Enum constants + * + * @psalm-pure + * @psalm-return array + * @return static[] Constant name in key, Enum instance in value + */ + public static function values() + { + $values = array(); + + /** @psalm-var T $value */ + foreach (static::toArray() as $key => $value) { + $values[$key] = new static($value); + } + + return $values; + } + + /** + * Returns all possible values as an array + * + * @psalm-pure + * @psalm-suppress ImpureStaticProperty + * + * @psalm-return array + * @return array Constant name in key, constant value in value + */ + public static function toArray() + { + $class = static::class; + + if (!isset(static::$cache[$class])) { + /** @psalm-suppress ImpureMethodCall this reflection API usage has no side-effects here */ + $reflection = new \ReflectionClass($class); + /** @psalm-suppress ImpureMethodCall this reflection API usage has no side-effects here */ + static::$cache[$class] = $reflection->getConstants(); + } + + return static::$cache[$class]; + } + + /** + * Check if is valid enum value + * + * @param $value + * @psalm-param mixed $value + * @psalm-pure + * @psalm-assert-if-true T $value + * @return bool + */ + public static function isValid($value) + { + return \in_array($value, static::toArray(), true); + } + + /** + * Asserts valid enum value + * + * @psalm-pure + * @psalm-assert T $value + * @param mixed $value + */ + public static function assertValidValue($value): void + { + self::assertValidValueReturningKey($value); + } + + /** + * Asserts valid enum value + * + * @psalm-pure + * @psalm-assert T $value + * @param mixed $value + * @return string + */ + private static function assertValidValueReturningKey($value): string + { + if (false === ($key = static::search($value))) { + throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class); + } + + return $key; + } + + /** + * Check if is valid enum key + * + * @param $key + * @psalm-param string $key + * @psalm-pure + * @return bool + */ + public static function isValidKey($key) + { + $array = static::toArray(); + + return isset($array[$key]) || \array_key_exists($key, $array); + } + + /** + * Return key for value + * + * @param mixed $value + * + * @psalm-param mixed $value + * @psalm-pure + * @return string|false + */ + public static function search($value) + { + return \array_search($value, static::toArray(), true); + } + + /** + * Returns a value when called statically like so: MyEnum::SOME_VALUE() given SOME_VALUE is a class constant + * + * @param string $name + * @param array $arguments + * + * @return static + * @throws \BadMethodCallException + * + * @psalm-pure + */ + public static function __callStatic($name, $arguments) + { + $class = static::class; + if (!isset(self::$instances[$class][$name])) { + $array = static::toArray(); + if (!isset($array[$name]) && !\array_key_exists($name, $array)) { + $message = "No static method or enum constant '$name' in class " . static::class; + throw new \BadMethodCallException($message); + } + return self::$instances[$class][$name] = new static($array[$name]); + } + return clone self::$instances[$class][$name]; + } + + /** + * Specify data which should be serialized to JSON. This method returns data that can be serialized by json_encode() + * natively. + * + * @return mixed + * @link http://php.net/manual/en/jsonserializable.jsonserialize.php + * @psalm-pure + */ + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + return $this->getValue(); + } +} diff --git a/vendor/myclabs/php-enum/src/PHPUnit/Comparator.php b/vendor/myclabs/php-enum/src/PHPUnit/Comparator.php new file mode 100644 index 000000000..302bf80eb --- /dev/null +++ b/vendor/myclabs/php-enum/src/PHPUnit/Comparator.php @@ -0,0 +1,54 @@ +register(new \MyCLabs\Enum\PHPUnit\Comparator()); + */ +final class Comparator extends \SebastianBergmann\Comparator\Comparator +{ + public function accepts($expected, $actual) + { + return $expected instanceof Enum && ( + $actual instanceof Enum || $actual === null + ); + } + + /** + * @param Enum $expected + * @param Enum|null $actual + * + * @return void + */ + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) + { + if ($expected->equals($actual)) { + return; + } + + throw new ComparisonFailure( + $expected, + $actual, + $this->formatEnum($expected), + $this->formatEnum($actual), + false, + 'Failed asserting that two Enums are equal.' + ); + } + + private function formatEnum(Enum $enum = null) + { + if ($enum === null) { + return "null"; + } + + return get_class($enum)."::{$enum->getKey()}()"; + } +} diff --git a/vendor/phpoffice/phpspreadsheet/.php-cs-fixer.dist.php b/vendor/phpoffice/phpspreadsheet/.php-cs-fixer.dist.php index db7072718..4179c6771 100644 --- a/vendor/phpoffice/phpspreadsheet/.php-cs-fixer.dist.php +++ b/vendor/phpoffice/phpspreadsheet/.php-cs-fixer.dist.php @@ -2,7 +2,6 @@ $finder = PhpCsFixer\Finder::create() ->exclude('vendor') - ->notPath('src/PhpSpreadsheet/Writer/ZipStream3.php') ->in(__DIR__); $config = new PhpCsFixer\Config(); diff --git a/vendor/phpoffice/phpspreadsheet/CHANGELOG.md b/vendor/phpoffice/phpspreadsheet/CHANGELOG.md index 38836217c..2f383e23f 100644 --- a/vendor/phpoffice/phpspreadsheet/CHANGELOG.md +++ b/vendor/phpoffice/phpspreadsheet/CHANGELOG.md @@ -5,67 +5,6 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com) and this project adheres to [Semantic Versioning](https://semver.org). -## 1.29.0 - 2023-06-15 - -### Added - -- Wizards for defining Number Format masks for Dates and Times, including Durations/Intervals. [PR #3458](https://github.com/PHPOffice/PhpSpreadsheet/pull/3458) -- Specify data type in html tags. [Issue #3444](https://github.com/PHPOffice/PhpSpreadsheet/issues/3444) [PR #3445](https://github.com/PHPOffice/PhpSpreadsheet/pull/3445) -- Provide option to ignore hidden rows/columns in `toArray()` methods. [PR #3494](https://github.com/PHPOffice/PhpSpreadsheet/pull/3494) -- Font/Effects/Theme support for Chart Data Labels and Axis. [PR #3476](https://github.com/PHPOffice/PhpSpreadsheet/pull/3476) -- Font Themes support. [PR #3486](https://github.com/PHPOffice/PhpSpreadsheet/pull/3486) -- Ability to Ignore Cell Errors in Excel. [Issue #1141](https://github.com/PHPOffice/PhpSpreadsheet/issues/1141) [PR #3508](https://github.com/PHPOffice/PhpSpreadsheet/pull/3508) -- Unzipped Gnumeric file [PR #3591](https://github.com/PHPOffice/PhpSpreadsheet/pull/3591) - -### Changed - -- Xlsx Color schemes read in will be written out (previously Excel 2007-2010 Color scheme was always written); manipulation of those schemes before write, including restoring prior behavior, is provided [PR #3476](https://github.com/PHPOffice/PhpSpreadsheet/pull/3476) -- Memory and speed optimisations for Read Filters with Xlsx Files and Shared Formulae. [PR #3474](https://github.com/PHPOffice/PhpSpreadsheet/pull/3474) -- Allow `CellRange` and `CellAddress` objects for the `range` argument in the `rangeToArray()` method. [PR #3494](https://github.com/PHPOffice/PhpSpreadsheet/pull/3494) -- Stock charts will now read and reproduce `upDownBars` and subsidiary tags; these were previously ignored on read and hard-coded on write. [PR #3515](https://github.com/PHPOffice/PhpSpreadsheet/pull/3515) - -### Deprecated - -- Nothing - -### Removed - -- Nothing - -### Fixed - -- Updates Cell formula absolute ranges/references, and Defined Name absolute ranges/references when inserting/deleting rows/columns. [Issue #3368](https://github.com/PHPOffice/PhpSpreadsheet/issues/3368) [PR #3402](https://github.com/PHPOffice/PhpSpreadsheet/pull/3402) -- EOMONTH() and EDATE() Functions should round date value before evaluation. [Issue #3436](https://github.com/PHPOffice/PhpSpreadsheet/issues/3436) [PR #3437](https://github.com/PHPOffice/PhpSpreadsheet/pull/3437) -- NETWORKDAYS function erroneously being converted to NETWORK_xlfn.DAYS in Xlsx Writer. [Issue #3461](https://github.com/PHPOffice/PhpSpreadsheet/issues/3461) [PR #3463](https://github.com/PHPOffice/PhpSpreadsheet/pull/3463) -- Getting a style for a CellAddress instance fails if the worksheet is set in the CellAddress instance. [Issue #3439](https://github.com/PHPOffice/PhpSpreadsheet/issues/3439) [PR #3469](https://github.com/PHPOffice/PhpSpreadsheet/pull/3469) -- Shared Formulae outside the filter range when reading with a filter are not always being identified. [Issue #3473](https://github.com/PHPOffice/PhpSpreadsheet/issues/3473) [PR #3474](https://github.com/PHPOffice/PhpSpreadsheet/pull/3474) -- Xls Reader Conditional Styles. [PR #3400](https://github.com/PHPOffice/PhpSpreadsheet/pull/3400) -- Allow use of # and 0 digit placeholders in fraction masks. [PR #3401](https://github.com/PHPOffice/PhpSpreadsheet/pull/3401) -- Modify Date/Time check in the NumberFormatter for decimal/fractional times. [PR #3413](https://github.com/PHPOffice/PhpSpreadsheet/pull/3413) -- Misplaced Xml Writing Chart Label FillColor. [Issue #3397](https://github.com/PHPOffice/PhpSpreadsheet/issues/3397) [PR #3404](https://github.com/PHPOffice/PhpSpreadsheet/pull/3404) -- TEXT function ignores Time in DateTimeStamp. [Issue #3409](https://github.com/PHPOffice/PhpSpreadsheet/issues/3409) [PR #3411](https://github.com/PHPOffice/PhpSpreadsheet/pull/3411) -- Xlsx Column Autosize Approximate for CJK. [Issue #3405](https://github.com/PHPOffice/PhpSpreadsheet/issues/3405) [PR #3416](https://github.com/PHPOffice/PhpSpreadsheet/pull/3416) -- Correct Xlsx Parsing of quotePrefix="0". [Issue #3435](https://github.com/PHPOffice/PhpSpreadsheet/issues/3435) [PR #3438](https://github.com/PHPOffice/PhpSpreadsheet/pull/3438) -- More Display Options for Chart Axis and Legend. [Issue #3414](https://github.com/PHPOffice/PhpSpreadsheet/issues/3414) [PR #3434](https://github.com/PHPOffice/PhpSpreadsheet/pull/3434) -- Apply strict type checking to Complex suffix. [PR #3452](https://github.com/PHPOffice/PhpSpreadsheet/pull/3452) -- Incorrect Font Color Read Xlsx Rich Text Indexed Color Custom Palette. [Issue #3464](https://github.com/PHPOffice/PhpSpreadsheet/issues/3464) [PR #3465](https://github.com/PHPOffice/PhpSpreadsheet/pull/3465) -- Xlsx Writer Honor Alignment in Default Font. [Issue #3443](https://github.com/PHPOffice/PhpSpreadsheet/issues/3443) [PR #3459](https://github.com/PHPOffice/PhpSpreadsheet/pull/3459) -- Support Border for Charts. [PR #3462](https://github.com/PHPOffice/PhpSpreadsheet/pull/3462) -- Error in "this row" structured reference calculation (cached result from first row when using a range) [Issue #3504](https://github.com/PHPOffice/PhpSpreadsheet/issues/3504) [PR #3505](https://github.com/PHPOffice/PhpSpreadsheet/pull/3505) -- Allow colour palette index references in Number Format masks [Issue #3511](https://github.com/PHPOffice/PhpSpreadsheet/issues/3511) [PR #3512](https://github.com/PHPOffice/PhpSpreadsheet/pull/3512) -- Xlsx Reader formula with quotePrefix [Issue #3495](https://github.com/PHPOffice/PhpSpreadsheet/issues/3495) [PR #3497](https://github.com/PHPOffice/PhpSpreadsheet/pull/3497) -- Handle REF error as part of range [Issue #3453](https://github.com/PHPOffice/PhpSpreadsheet/issues/3453) [PR #3467](https://github.com/PHPOffice/PhpSpreadsheet/pull/3467) -- Handle Absolute Pathnames in Rels File [Issue #3553](https://github.com/PHPOffice/PhpSpreadsheet/issues/3553) [PR #3554](https://github.com/PHPOffice/PhpSpreadsheet/pull/3554) -- Return Page Breaks in Order [Issue #3552](https://github.com/PHPOffice/PhpSpreadsheet/issues/3552) [PR #3555](https://github.com/PHPOffice/PhpSpreadsheet/pull/3555) -- Add position attribute for MemoryDrawing in Html [Issue #3529](https://github.com/PHPOffice/PhpSpreadsheet/issues/3529 [PR #3535](https://github.com/PHPOffice/PhpSpreadsheet/pull/3535) -- Allow Index_number as Array for VLOOKUP/HLOOKUP [Issue #3561](https://github.com/PHPOffice/PhpSpreadsheet/issues/3561 [PR #3570](https://github.com/PHPOffice/PhpSpreadsheet/pull/3570) -- Add Unsupported Options in Xml Spreadsheet [Issue #3566](https://github.com/PHPOffice/PhpSpreadsheet/issues/3566 [Issue #3568](https://github.com/PHPOffice/PhpSpreadsheet/issues/3568 [Issue #3569](https://github.com/PHPOffice/PhpSpreadsheet/issues/3569 [PR #3567](https://github.com/PHPOffice/PhpSpreadsheet/pull/3567) -- Changes to NUMBERVALUE, VALUE, DATEVALUE, TIMEVALUE [Issue #3574](https://github.com/PHPOffice/PhpSpreadsheet/issues/3574 [PR #3575](https://github.com/PHPOffice/PhpSpreadsheet/pull/3575) -- Redo calculation of color tinting [Issue #3550](https://github.com/PHPOffice/PhpSpreadsheet/issues/3550) [PR #3580](https://github.com/PHPOffice/PhpSpreadsheet/pull/3580) -- Accommodate Slash with preg_quote [PR #3582](https://github.com/PHPOffice/PhpSpreadsheet/pull/3582) [PR #3583](https://github.com/PHPOffice/PhpSpreadsheet/pull/3583) [PR #3584](https://github.com/PHPOffice/PhpSpreadsheet/pull/3584) -- HyperlinkBase Property and Html Handling of Properties [Issue #3573](https://github.com/PHPOffice/PhpSpreadsheet/issues/3573) [PR #3589](https://github.com/PHPOffice/PhpSpreadsheet/pull/3589) -- Improvements for Data Validation [Issue #3592](https://github.com/PHPOffice/PhpSpreadsheet/issues/3592) [Issue #3594](https://github.com/PHPOffice/PhpSpreadsheet/issues/3594) [PR #3605](https://github.com/PHPOffice/PhpSpreadsheet/pull/3605) - ## 1.28.0 - 2023-02-25 ### Added diff --git a/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md b/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md index 09794b565..f59535331 100644 --- a/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md +++ b/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md @@ -2,44 +2,19 @@ If you would like to contribute, here are some notes and guidelines: - - All new development should be on feature/fix branches, which are then merged to the `master` branch once stable and approved; so the `master` branch is always the most up-to-date, working code - - If you are going to submit a pull request, please fork from `master`, and submit your pull request back as a fix/feature branch referencing the GitHub issue number - - The code must work with all PHP versions that we support (currently PHP 7.4 to PHP 8.2). - - You can call `composer versions` to test version compatibility. - - Code style should be maintained. - - `composer style` will identify any issues with Coding Style`. - - `composer fix` will fix most issues with Coding Style. - - All code changes must be validated by `composer check`. - - Please include Unit Tests to verify that a bug exists, and that this PR fixes it. - - Please include Unit Tests to show that a new Feature works as expected. - - Please don't "bundle" several changes into a single PR; submit a PR for each discrete change/fix. - - Remember to update documentation if necessary. - + - All new development happens on feature/fix branches, and are then merged to the `master` branch once stable; so the `master` branch is always the most up-to-date, working code + - Tagged releases are made from the `master` branch + - If you are going to be submitting a pull request, please fork from `master`, and submit your pull request back as a fix/feature branch referencing the GitHub issue number + - Code style might be automatically fixed by `composer fix` + - All code changes must be validated by `composer check` - [Helpful article about forking](https://help.github.com/articles/fork-a-repo/ "Forking a GitHub repository") - [Helpful article about pull requests](https://help.github.com/articles/using-pull-requests/ "Pull Requests") -## Unit Tests - -When writing Unit Tests, please - - Always try to write Unit Tests for both the happy and unhappy paths. - - Put all assertions in the Test itself, not in an abstract class that the Test extends (even if this means code duplication between tests). - - Include any necessary `setup()` and `tearDown()` in the Test itself. - - If you change any global settings (such as system locale, or Compatibility Mode for Excel Function tests), make sure that you reset to the default in the `tearDown()`. - - Use the `ExcelError` functions in assertions for Excel Error values in Excel Function implementations. -
Not only does it reduce the risk of typos; but at some point in the future, ExcelError values will be an object rather than a string, and we won't then need to update all the tests. - - Don't over-complicate test code by testing happy and unhappy paths in the same test. - -This makes it easier to see exactly what is being tested when reviewing the PR. I want to be able to see it in the PR, not have to hunt in other unchanged classes to see what the test is doing. - ## How to release 1. Complete CHANGELOG.md and commit 2. Create an annotated tag 1. `git tag -a 1.2.3` 2. Tag subject must be the version number, eg: `1.2.3` - 3. Tag body must be a copy-paste of the changelog entries. -3. Push the tag with `git push --tags`, GitHub Actions will create a GitHub release automatically, and the release details will automatically be sent to packagist. -4. Github seems to remove markdown headings in the Release Notes, so you should edit to restore these. - -> **Note:** Tagged releases are made from the `master` branch. Only in an emergency should a tagged release be made from the `release` branch. (i.e. cherry-picked hot-fixes.) - + 3. Tag body must be a copy-paste of the changelog entries +3. Push tag with `git push --tags`, GitHub Actions will create a GitHub release automatically diff --git a/vendor/phpoffice/phpspreadsheet/README.md b/vendor/phpoffice/phpspreadsheet/README.md index a69c3afc9..d9a807326 100644 --- a/vendor/phpoffice/phpspreadsheet/README.md +++ b/vendor/phpoffice/phpspreadsheet/README.md @@ -32,7 +32,7 @@ If you are building your installation on a development machine that is on a diff ```json { "require": { - "phpoffice/phpspreadsheet": "^1.28" + "phpoffice/phpspreadsheet": "^1.23" }, "config": { "platform": { @@ -74,20 +74,16 @@ or the appropriate PDF Writer wrapper for the library that you have chosen to in For Chart export, we support following packages, which you will also need to install yourself using `composer require` - [jpgraph/jpgraph](https://packagist.org/packages/jpgraph/jpgraph) (this package was abandoned at version 4.0. You can manually download the latest version that supports PHP 8 and above from [jpgraph.net](https://jpgraph.net/)) - - [mitoteam/jpgraph](https://packagist.org/packages/mitoteam/jpgraph) - up to date fork with modern PHP versions support and some bugs fixed. + - [mitoteam/jpgraph](https://packagist.org/packages/mitoteam/jpgraph) (fork with php 8.1 support) and then configure PhpSpreadsheet using: ```php -// to use jpgraph/jpgraph -Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); +Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); // to use jpgraph/jpgraph //or -// to use mitoteam/jpgraph -Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); +Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); // to use mitoteam/jpgraph ``` -One or the other of these libraries is necessary if you want to generate HTML or PDF files that include charts; or to render a Chart to an Image format from within your code. -They are not necessary to define charts for writing to `Xlsx` files. -Other file formats don't support writing Charts. +One or the other of these libraries is necessary if you want to generate HTML or PDF files that include charts. ## Documentation @@ -107,15 +103,10 @@ Posts already available to Patreon supporters: - Looping the Loop - Advice on Iterating through the rows and cells in a worksheet. -And for Patrons at levels actively using PhpSpreadsheet: +The next post (currently being written) will be: - Behind the Mask - A look at Number Format Masks. -The Next Article (currently Work in Progress): - - Formula for Success - - How to debug formulae that don't produce the expected result. - - My aim is to post at least one article each month, taking a detailed look at some feature of MS Excel and how to use that feature in PhpSpreadsheet, or on how to perform different activities in PhpSpreadsheet. Planned posts for the future include topics like: @@ -125,9 +116,8 @@ Planned posts for the future include topics like: - Array Formulae - Conditional Formatting - Data Validation + - Formula Debugging - Value Binders - - Images - - Charts After a period of six months exclusive to Patreon supporters, articles will be incorporated into the public documentation for the library. diff --git a/vendor/phpoffice/phpspreadsheet/composer.json b/vendor/phpoffice/phpspreadsheet/composer.json index 4b05be334..1e8e5f6c0 100644 --- a/vendor/phpoffice/phpspreadsheet/composer.json +++ b/vendor/phpoffice/phpspreadsheet/composer.json @@ -42,19 +42,13 @@ ], "scripts": { "check": [ - "phpcs src/ tests/ --report=checkstyle", - "phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PHPCompatibility --runtime-set testVersion 7.4- -n", "php-cs-fixer fix --ansi --dry-run --diff", + "phpcs", "phpunit --color=always", - "phpstan analyse --ansi --memory-limit=2048M" - ], - "style": [ - "phpcs src/ tests/ --report=checkstyle", - "php-cs-fixer fix --ansi --dry-run --diff" + "phpstan analyse --ansi" ], "fix": [ - "phpcbf src/ tests/ --report=checkstyle", - "php-cs-fixer fix" + "php-cs-fixer fix --ansi" ], "versions": [ "phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PHPCompatibility --runtime-set testVersion 7.4- -n" @@ -76,7 +70,7 @@ "ext-zip": "*", "ext-zlib": "*", "ezyang/htmlpurifier": "^4.15", - "maennchen/zipstream-php": "^2.1 || ^3.0", + "maennchen/zipstream-php": "^2.1", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", "psr/http-client": "^1.0", @@ -87,12 +81,12 @@ "dealerdirect/phpcodesniffer-composer-installer": "dev-main", "dompdf/dompdf": "^1.0 || ^2.0", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.3", + "mitoteam/jpgraph": "^10.2.4", "mpdf/mpdf": "^8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0 || ^10.0", + "phpunit/phpunit": "^8.5 || ^9.0", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, diff --git a/vendor/phpoffice/phpspreadsheet/phpstan.neon.dist b/vendor/phpoffice/phpspreadsheet/phpstan.neon.dist index ef2ae14fa..30bd6c2f7 100644 --- a/vendor/phpoffice/phpspreadsheet/phpstan.neon.dist +++ b/vendor/phpoffice/phpspreadsheet/phpstan.neon.dist @@ -12,10 +12,6 @@ parameters: excludePaths: - src/PhpSpreadsheet/Chart/Renderer/JpGraph.php - src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php - - src/PhpSpreadsheet/Collection/Memory/SimpleCache1.php - - src/PhpSpreadsheet/Collection/Memory/SimpleCache3.php - - src/PhpSpreadsheet/Writer/ZipStream2.php - - src/PhpSpreadsheet/Writer/ZipStream3.php parallel: processTimeout: 300.0 checkMissingIterableValueType: false diff --git a/vendor/phpoffice/phpspreadsheet/phpunit10.xml.dist b/vendor/phpoffice/phpspreadsheet/phpunit10.xml.dist deleted file mode 100644 index 207d8ec97..000000000 --- a/vendor/phpoffice/phpspreadsheet/phpunit10.xml.dist +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - ./tests/PhpSpreadsheetTests - - - - ./src - - - diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php index c88656b4a..6de546fa2 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php @@ -19,7 +19,6 @@ use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use ReflectionClassConstant; use ReflectionMethod; use ReflectionParameter; -use Throwable; class Calculation { @@ -3557,7 +3556,7 @@ class Calculation } } - throw new Exception($e->getMessage(), $e->getCode(), $e); + throw new Exception($e->getMessage()); } if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { @@ -4211,7 +4210,7 @@ class Calculation try { $this->branchPruner->closingBrace($d['value']); } catch (Exception $e) { - return $this->raiseFormulaError($e->getMessage(), $e->getCode(), $e); + return $this->raiseFormulaError($e->getMessage()); } $functionName = $matches[1]; // Get the function name @@ -4250,7 +4249,7 @@ class Calculation } elseif ($expectedArgumentCount != '*') { $isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/', $expectedArgumentCount, $argMatch); self::doNothing($isOperandOrFunction); - switch ($argMatch[2] ?? '') { + switch ($argMatch[2]) { case '+': if ($argumentCount < $argMatch[1]) { $argumentCountError = true; @@ -4283,7 +4282,7 @@ class Calculation try { $this->branchPruner->argumentSeparator(); } catch (Exception $e) { - return $this->raiseFormulaError($e->getMessage(), $e->getCode(), $e); + return $this->raiseFormulaError($e->getMessage()); } while (($o2 = $stack->pop()) && $o2['value'] !== '(') { // Pop off the stack back to the last ( @@ -4365,12 +4364,8 @@ class Calculation $rangeStartCellRef = $output[count($output) - 2]['value'] ?? ''; } preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/miu', $rangeStartCellRef, $rangeStartMatches); - if (array_key_exists(2, $rangeStartMatches)) { - if ($rangeStartMatches[2] > '') { - $val = $rangeStartMatches[2] . '!' . $val; - } - } else { - $val = Information\ExcelError::REF(); + if ($rangeStartMatches[2] > '') { + $val = $rangeStartMatches[2] . '!' . $val; } } else { $rangeStartCellRef = $output[count($output) - 1]['value'] ?? ''; @@ -4396,7 +4391,7 @@ class Calculation try { $structuredReference = Operands\StructuredReference::fromParser($formula, $index, $matches); } catch (Exception $e) { - return $this->raiseFormulaError($e->getMessage(), $e->getCode(), $e); + return $this->raiseFormulaError($e->getMessage()); } $val = $structuredReference->value(); @@ -4439,8 +4434,6 @@ class Calculation } $val = $address; } - } elseif ($val === Information\ExcelError::REF()) { - $stackItemReference = $val; } else { $startRowColRef = $output[count($output) - 1]['value'] ?? ''; [$rangeWS1, $startRowColRef] = Worksheet::extractSheetTitle($startRowColRef, true); @@ -4738,7 +4731,7 @@ class Calculation $cellRange = $token->parse($cell); if (strpos($cellRange, ':') !== false) { $this->debugLog->writeDebugLog('Evaluating Structured Reference %s as Cell Range %s', $token->value(), $cellRange); - $rangeValue = self::getInstance($cell->getWorksheet()->getParent())->_calculateFormulaValue("={$cellRange}", $cellRange, $cell); + $rangeValue = self::getInstance($cell->getWorksheet()->getParent())->_calculateFormulaValue("={$cellRange}", $token->value(), $cell); $stack->push('Value', $rangeValue); $this->debugLog->writeDebugLog('Evaluated Structured Reference %s as value %s', $token->value(), $this->showValue($rangeValue)); } else { @@ -4752,7 +4745,7 @@ class Calculation $stack->push('Error', Information\ExcelError::REF(), null); $this->debugLog->writeDebugLog('Evaluated Structured Reference %s as error value %s', $token->value(), Information\ExcelError::REF()); } else { - return $this->raiseFormulaError($e->getMessage(), $e->getCode(), $e); + return $this->raiseFormulaError($e->getMessage()); } } } elseif (!is_numeric($token) && !is_object($token) && isset(self::BINARY_OPERATORS[$token])) { @@ -4800,7 +4793,7 @@ class Calculation } } } - if (strpos($operand1Data['reference'] ?? '', '!') !== false) { + if (strpos($operand1Data['reference'], '!') !== false) { [$sheet1, $operand1Data['reference']] = Worksheet::extractSheetTitle($operand1Data['reference'], true); } else { $sheet1 = ($pCellWorksheet !== null) ? $pCellWorksheet->getTitle() : ''; @@ -4837,21 +4830,10 @@ class Calculation $oData = array_merge(explode(':', $operand1Data['reference']), explode(':', $operand2Data['reference'])); $oCol = $oRow = []; - $breakNeeded = false; foreach ($oData as $oDatum) { - try { - $oCR = Coordinate::coordinateFromString($oDatum); - $oCol[] = Coordinate::columnIndexFromString($oCR[0]) - 1; - $oRow[] = $oCR[1]; - } catch (\Exception $e) { - $stack->push('Error', Information\ExcelError::REF(), null); - $breakNeeded = true; - - break; - } - } - if ($breakNeeded) { - break; + $oCR = Coordinate::coordinateFromString($oDatum); + $oCol[] = Coordinate::columnIndexFromString($oCR[0]) - 1; + $oRow[] = $oCR[1]; } $cellRef = Coordinate::stringFromColumnIndex(min($oCol) + 1) . min($oRow) . ':' . Coordinate::stringFromColumnIndex(max($oCol) + 1) . max($oRow); if ($pCellParent !== null && $this->spreadsheet !== null) { @@ -4860,10 +4842,8 @@ class Calculation return $this->raiseFormulaError('Unable to access Cell Reference'); } - $this->debugLog->writeDebugLog('Evaluation Result is %s', $this->showTypeDetails($cellValue)); $stack->push('Cell Reference', $cellValue, $cellRef); } else { - $this->debugLog->writeDebugLog('Evaluation Result is a #REF! Error'); $stack->push('Error', Information\ExcelError::REF(), null); } @@ -5454,13 +5434,13 @@ class Calculation * * @return false */ - protected function raiseFormulaError(string $errorMessage, int $code = 0, ?Throwable $exception = null) + protected function raiseFormulaError(string $errorMessage) { $this->formulaError = $errorMessage; $this->cyclicReferenceStack->clear(); $suppress = /** @scrutinizer ignore-deprecated */ $this->suppressFormulaErrors ?? $this->suppressFormulaErrorsNew; if (!$suppress) { - throw new Exception($errorMessage, $code, $exception); + throw new Exception($errorMessage); } return false; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php index 1d59988c3..9a9870d91 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php @@ -45,11 +45,6 @@ class DateValue return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $dateValue); } - // try to parse as date iff there is at least one digit - if (is_string($dateValue) && preg_match('/\\d/', $dateValue) !== 1) { - return ExcelError::VALUE(); - } - $dti = new DateTimeImmutable(); $baseYear = SharedDateHelper::getExcelCalendar(); $dateValue = trim($dateValue ?? '', '"'); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php index 5c42eac08..c72d006b9 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php @@ -45,7 +45,6 @@ class Month } catch (Exception $e) { return $e->getMessage(); } - $dateValue = floor($dateValue); $adjustmentMonths = floor($adjustmentMonths); // Execute function @@ -89,7 +88,6 @@ class Month } catch (Exception $e) { return $e->getMessage(); } - $dateValue = floor($dateValue); $adjustmentMonths = floor($adjustmentMonths); // Execute function diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php index 78d67b837..bb9036f78 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php @@ -42,11 +42,6 @@ class TimeValue return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $timeValue); } - // try to parse as time iff there is at least one digit - if (is_string($timeValue) && preg_match('/\\d/', $timeValue) !== 1) { - return ExcelError::VALUE(); - } - $timeValue = trim($timeValue ?? '', '"'); $timeValue = str_replace(['/', '.'], '-', $timeValue); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php index 331fa448b..3e88ece55 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php @@ -48,9 +48,9 @@ class FormattedNumber */ public static function convertToNumberIfNumeric(string &$operand): bool { - $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/'); + $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator()); $value = preg_replace(['/(\d)' . $thousandsSeparator . '(\d)/u', '/([+-])\s+(\d)/u'], ['$1$2', '$1$2'], trim($operand)); - $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator(), '/'); + $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator()); $value = preg_replace(['/(\d)' . $decimalSeparator . '(\d)/u', '/([+-])\s+(\d)/u'], ['$1.$2', '$1$2'], $value ?? ''); if (is_numeric($value)) { @@ -90,9 +90,9 @@ class FormattedNumber */ public static function convertToNumberIfPercent(string &$operand): bool { - $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/'); + $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator()); $value = preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', trim($operand)); - $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator(), '/'); + $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator()); $value = preg_replace(['/(\d)' . $decimalSeparator . '(\d)/u', '/([+-])\s+(\d)/u'], ['$1.$2', '$1$2'], $value ?? ''); $match = []; @@ -116,22 +116,17 @@ class FormattedNumber public static function convertToNumberIfCurrency(string &$operand): bool { $currencyRegexp = self::currencyMatcherRegexp(); - $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/'); + $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator()); $value = preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $operand); $match = []; if ($value !== null && preg_match($currencyRegexp, $value, $match, PREG_UNMATCHED_AS_NULL)) { //Determine the sign $sign = ($match['PrefixedSign'] ?? $match['PrefixedSign2'] ?? $match['PostfixedSign']) ?? ''; - $decimalSeparator = StringHelper::getDecimalSeparator(); //Cast to a float - $intermediate = (string) ($match['PostfixedValue'] ?? $match['PrefixedValue']); - $intermediate = str_replace($decimalSeparator, '.', $intermediate); - if (is_numeric($intermediate)) { - $operand = (float) ($sign . str_replace($decimalSeparator, '.', $intermediate)); + $operand = (float) ($sign . ($match['PostfixedValue'] ?? $match['PrefixedValue'])); - return true; - } + return true; } return false; @@ -139,8 +134,8 @@ class FormattedNumber public static function currencyMatcherRegexp(): string { - $currencyCodes = sprintf(self::CURRENCY_CONVERSION_LIST, preg_quote(StringHelper::getCurrencyCode(), '/')); - $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator(), '/'); + $currencyCodes = sprintf(self::CURRENCY_CONVERSION_LIST, preg_quote(StringHelper::getCurrencyCode())); + $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator()); return '~^(?:(?: *(?[-+])? *(?[' . $currencyCodes . ']) *(?[-+])? *(?[0-9]+[' . $decimalSeparator . ']?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?[-+])? *(?[0-9]+' . $decimalSeparator . '?[0-9]*(?:E[-+]?[0-9]*)?) *(?[' . $currencyCodes . ']) *))$~ui'; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php index 59cc3e3d2..266f1b2bb 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php @@ -190,8 +190,8 @@ final class StructuredReference implements Operand { if ($columnName !== '') { $cellReference = $columnId . $cell->getRow(); - $pattern1 = '/\[' . preg_quote($columnName, '/') . '\]/miu'; - $pattern2 = '/@' . preg_quote($columnName, '/') . '/miu'; + $pattern1 = '/\[' . preg_quote($columnName) . '\]/miu'; + $pattern2 = '/@' . preg_quote($columnName) . '/miu'; if (preg_match($pattern1, $reference) === 1) { $reference = preg_replace($pattern1, $cellReference, $reference); } elseif (preg_match($pattern2, $reference) === 1) { @@ -328,7 +328,7 @@ final class StructuredReference implements Operand $cellFrom = "{$columnId}{$startRow}"; $cellTo = "{$columnId}{$endRow}"; $cellReference = ($cellFrom === $cellTo) ? $cellFrom : "{$cellFrom}:{$cellTo}"; - $pattern = '/\[' . preg_quote($columnName, '/') . '\]/mui'; + $pattern = '/\[' . preg_quote($columnName) . '\]/mui'; if (preg_match($pattern, $reference) === 1) { $columnsSelected = true; $reference = preg_replace($pattern, $cellReference, $reference); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php index fdee7503e..e3a2bd65c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php @@ -20,6 +20,28 @@ class Engineering */ public const EULER = 2.71828182845904523536; + /** + * parseComplex. + * + * Parses a complex number into its real and imaginary parts, and an I or J suffix + * + * @deprecated 1.12.0 No longer used by internal code. Please use the \Complex\Complex class instead + * + * @param string $complexNumber The complex number + * + * @return mixed[] Indexed on "real", "imaginary" and "suffix" + */ + public static function parseComplex($complexNumber) + { + $complex = new Complex($complexNumber); + + return [ + 'real' => $complex->getReal(), + 'imaginary' => $complex->getImaginary(), + 'suffix' => $complex->getSuffix(), + ]; + } + /** * BESSELI. * diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php index f7ec02d43..691de8b70 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php @@ -49,7 +49,7 @@ class Complex return $e->getMessage(); } - if (($suffix === 'i') || ($suffix === 'j') || ($suffix === '')) { + if (($suffix == 'i') || ($suffix == 'j') || ($suffix == '')) { $complex = new ComplexObject($realNumber, $imaginary, $suffix); return (string) $complex; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php index 04bf3e506..4741f3010 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php @@ -40,7 +40,7 @@ class ConvertBinary extends ConvertBase return $e->getMessage(); } - if (strlen($value) == 10 && $value[0] === '1') { + if (strlen($value) == 10) { // Two's Complement $value = substr($value, -9); @@ -91,7 +91,7 @@ class ConvertBinary extends ConvertBase return $e->getMessage(); } - if (strlen($value) == 10 && $value[0] === '1') { + if (strlen($value) == 10) { $high2 = substr($value, 0, 2); $low8 = substr($value, 2); $xarr = ['00' => '00000000', '01' => '00000001', '10' => 'FFFFFFFE', '11' => 'FFFFFFFF']; @@ -144,7 +144,7 @@ class ConvertBinary extends ConvertBase return $e->getMessage(); } - if (strlen($value) == 10 && $value[0] === '1') { // Two's Complement + if (strlen($value) == 10 && substr($value, 0, 1) === '1') { // Two's Complement return str_repeat('7', 6) . strtoupper(decoct((int) bindec("11$value"))); } $octVal = (string) decoct((int) bindec($value)); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php index bc425f873..e2d27bde2 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php @@ -27,7 +27,7 @@ class HLookup extends LookupBase */ public static function lookup($lookupValue, $lookupArray, $indexNumber, $notExactMatch = true) { - if (is_array($lookupValue) || is_array($indexNumber)) { + if (is_array($lookupValue)) { return self::evaluateArrayArgumentsIgnore([self::class, __FUNCTION__], 1, $lookupValue, $lookupArray, $indexNumber, $notExactMatch); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php index badd10573..edeb1aa8c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php @@ -26,7 +26,7 @@ class VLookup extends LookupBase */ public static function lookup($lookupValue, $lookupArray, $indexNumber, $notExactMatch = true) { - if (is_array($lookupValue) || is_array($indexNumber)) { + if (is_array($lookupValue)) { return self::evaluateArrayArgumentsIgnore([self::class, __FUNCTION__], 1, $lookupValue, $lookupArray, $indexNumber, $notExactMatch); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php index 56b0861c6..1a797c8a2 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php @@ -66,8 +66,8 @@ class Sum $returnValue += (int) $arg; } elseif (ErrorValue::isError($arg)) { return $arg; + // ignore non-numerics from cell, but fail as literals (except null) } elseif ($arg !== null && !Functions::isCellValue($k)) { - // ignore non-numerics from cell, but fail as literals (except null) return ExcelError::VALUE(); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php index 24ddff2ec..519607c08 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php @@ -261,7 +261,7 @@ class Extract $delimiter = Functions::flattenArray($delimiter); $quotedDelimiters = array_map( function ($delimiter) { - return preg_quote($delimiter ?? '', '/'); + return preg_quote($delimiter ?? ''); }, $delimiter ); @@ -270,7 +270,7 @@ class Extract return '(' . $delimiters . ')'; } - return '(' . preg_quote($delimiter ?? '', '/') . ')'; + return '(' . preg_quote($delimiter ?? '') . ')'; } private static function matchFlags(int $matchMode): string diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php index 57d331663..93e728202 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php @@ -129,7 +129,7 @@ class Format $format = Helpers::extractString($format); if (!is_numeric($value) && Date::isDateTimeFormatCode($format)) { - $value = DateTimeExcel\DateValue::fromString($value) + DateTimeExcel\TimeValue::fromString($value); + $value = DateTimeExcel\DateValue::fromString($value); } return (string) NumberFormat::toFormattedString($value, $format); @@ -140,7 +140,7 @@ class Format * * @return mixed */ - private static function convertValue($value, bool $spacesMeanZero = false) + private static function convertValue($value) { $value = $value ?? 0; if (is_bool($value)) { @@ -150,12 +150,6 @@ class Format throw new CalcExp(ExcelError::VALUE()); } } - if (is_string($value)) { - $value = trim($value); - if ($spacesMeanZero && $value === '') { - $value = 0; - } - } return $value; } @@ -187,9 +181,6 @@ class Format '', trim($value, " \t\n\r\0\x0B" . StringHelper::getCurrencyCode()) ); - if ($numberValue === '') { - return ExcelError::VALUE(); - } if (is_numeric($numberValue)) { return (float) $numberValue; } @@ -286,7 +277,7 @@ class Format } try { - $value = self::convertValue($value, true); + $value = self::convertValue($value); $decimalSeparator = self::getDecimalSeparator($decimalSeparator); $groupSeparator = self::getGroupSeparator($groupSeparator); } catch (CalcExp $e) { @@ -294,12 +285,12 @@ class Format } if (!is_numeric($value)) { - $decimalPositions = preg_match_all('/' . preg_quote($decimalSeparator, '/') . '/', $value, $matches, PREG_OFFSET_CAPTURE); + $decimalPositions = preg_match_all('/' . preg_quote($decimalSeparator) . '/', $value, $matches, PREG_OFFSET_CAPTURE); if ($decimalPositions > 1) { return ExcelError::VALUE(); } - $decimalOffset = array_pop($matches[0])[1] ?? null; - if ($decimalOffset === null || strpos($value, $groupSeparator, $decimalOffset) !== false) { + $decimalOffset = array_pop($matches[0])[1]; // @phpstan-ignore-line + if (strpos($value, $groupSeparator, $decimalOffset) !== false) { return ExcelError::VALUE(); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php index b8a730767..8e6a575a2 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php @@ -193,7 +193,7 @@ class Text if (is_array($delimiter) && count($valueSet) > 1) { $quotedDelimiters = array_map( function ($delimiter) { - return preg_quote($delimiter ?? '', '/'); + return preg_quote($delimiter ?? ''); }, $valueSet ); @@ -202,7 +202,7 @@ class Text return '(' . $delimiters . ')'; } - return '(' . preg_quote(/** @scrutinizer ignore-type */ Functions::flattenSingleValue($delimiter), '/') . ')'; + return '(' . preg_quote(/** @scrutinizer ignore-type */ Functions::flattenSingleValue($delimiter)) . ')'; } private static function matchFlags(bool $matchMode): string diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php index c0fb38775..1bf73ba82 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php @@ -51,9 +51,8 @@ class AdvancedValueBinder extends DefaultValueBinder implements IValueBinder return $this->setImproperFraction($matches, $cell); } - $decimalSeparatorNoPreg = StringHelper::getDecimalSeparator(); - $decimalSeparator = preg_quote($decimalSeparatorNoPreg, '/'); - $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/'); + $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator()); + $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator()); // Check for percentage if (preg_match('/^\-?\d*' . $decimalSeparator . '?\d*\s?\%$/', preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $value))) { @@ -65,7 +64,7 @@ class AdvancedValueBinder extends DefaultValueBinder implements IValueBinder // Convert value to number $sign = ($matches['PrefixedSign'] ?? $matches['PrefixedSign2'] ?? $matches['PostfixedSign']) ?? null; $currencyCode = $matches['PrefixedCurrency'] ?? $matches['PostfixedCurrency']; - $value = (float) ($sign . trim(str_replace([$decimalSeparatorNoPreg, $currencyCode, ' ', '-'], ['.', '', '', ''], preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $value)))); // @phpstan-ignore-line + $value = (float) ($sign . trim(str_replace([$decimalSeparator, $currencyCode, ' ', '-'], ['.', '', '', ''], preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', $value)))); // @phpstan-ignore-line return $this->setCurrency($value, $cell, $currencyCode); // @phpstan-ignore-line } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php index e9e41d7c7..a53294e53 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php @@ -71,9 +71,6 @@ class Cell */ private $formulaAttributes; - /** @var IgnoredErrors */ - private $ignoredErrors; - /** * Update the cell into the cell collection. * @@ -122,7 +119,6 @@ class Cell } elseif (self::getValueBinder()->bindValue($this, $value) === false) { throw new Exception('Value could not be bound to cell.'); } - $this->ignoredErrors = new IgnoredErrors(); } /** @@ -395,9 +391,7 @@ class Cell } throw new \PhpOffice\PhpSpreadsheet\Calculation\Exception( - $this->getWorksheet()->getTitle() . '!' . $this->getCoordinate() . ' -> ' . $ex->getMessage(), - $ex->getCode(), - $ex + $this->getWorksheet()->getTitle() . '!' . $this->getCoordinate() . ' -> ' . $ex->getMessage() ); } @@ -800,9 +794,4 @@ class Cell { return (string) $this->getValue(); } - - public function getIgnoredErrors(): IgnoredErrors - { - return $this->ignoredErrors; - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php index 692f316ec..0e395a7ff 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php @@ -20,7 +20,7 @@ class DataValidator */ public function isValid(Cell $cell) { - if (!$cell->hasDataValidation() || $cell->getDataValidation()->getType() === DataValidation::TYPE_NONE) { + if (!$cell->hasDataValidation()) { return true; } @@ -31,55 +31,13 @@ class DataValidator return false; } - $returnValue = false; - $type = $dataValidation->getType(); - if ($type === DataValidation::TYPE_LIST) { - $returnValue = $this->isValueInList($cell); - } elseif ($type === DataValidation::TYPE_WHOLE) { - if (!is_numeric($cellValue) || fmod((float) $cellValue, 1) != 0) { - $returnValue = false; - } else { - $returnValue = $this->numericOperator($dataValidation, (int) $cellValue); - } - } elseif ($type === DataValidation::TYPE_DECIMAL || $type === DataValidation::TYPE_DATE || $type === DataValidation::TYPE_TIME) { - if (!is_numeric($cellValue)) { - $returnValue = false; - } else { - $returnValue = $this->numericOperator($dataValidation, (float) $cellValue); - } - } elseif ($type === DataValidation::TYPE_TEXTLENGTH) { - $returnValue = $this->numericOperator($dataValidation, mb_strlen((string) $cellValue)); + // TODO: write check on all cases + switch ($dataValidation->getType()) { + case DataValidation::TYPE_LIST: + return $this->isValueInList($cell); } - return $returnValue; - } - - /** @param float|int $cellValue */ - private function numericOperator(DataValidation $dataValidation, $cellValue): bool - { - $operator = $dataValidation->getOperator(); - $formula1 = $dataValidation->getFormula1(); - $formula2 = $dataValidation->getFormula2(); - $returnValue = false; - if ($operator === DataValidation::OPERATOR_BETWEEN) { - $returnValue = $cellValue >= $formula1 && $cellValue <= $formula2; - } elseif ($operator === DataValidation::OPERATOR_NOTBETWEEN) { - $returnValue = $cellValue < $formula1 || $cellValue > $formula2; - } elseif ($operator === DataValidation::OPERATOR_EQUAL) { - $returnValue = $cellValue == $formula1; - } elseif ($operator === DataValidation::OPERATOR_NOTEQUAL) { - $returnValue = $cellValue != $formula1; - } elseif ($operator === DataValidation::OPERATOR_LESSTHAN) { - $returnValue = $cellValue < $formula1; - } elseif ($operator === DataValidation::OPERATOR_LESSTHANOREQUAL) { - $returnValue = $cellValue <= $formula1; - } elseif ($operator === DataValidation::OPERATOR_GREATERTHAN) { - $returnValue = $cellValue > $formula1; - } elseif ($operator === DataValidation::OPERATOR_GREATERTHANOREQUAL) { - $returnValue = $cellValue >= $formula1; - } - - return $returnValue; + return false; } /** diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IgnoredErrors.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IgnoredErrors.php deleted file mode 100644 index ee4b51562..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IgnoredErrors.php +++ /dev/null @@ -1,66 +0,0 @@ -numberStoredAsText = $value; - - return $this; - } - - public function getNumberStoredAsText(): bool - { - return $this->numberStoredAsText; - } - - public function setFormula(bool $value): self - { - $this->formula = $value; - - return $this; - } - - public function getFormula(): bool - { - return $this->formula; - } - - public function setTwoDigitTextYear(bool $value): self - { - $this->twoDigitTextYear = $value; - - return $this; - } - - public function getTwoDigitTextYear(): bool - { - return $this->twoDigitTextYear; - } - - public function setEvalError(bool $value): self - { - $this->evalError = $value; - - return $this; - } - - public function getEvalError(): bool - { - return $this->evalError; - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php index 0e164543b..24694d5c6 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php @@ -118,7 +118,7 @@ class CellReferenceHelper { $newColumn = Coordinate::stringFromColumnIndex(min($newColumnIndex + $this->numberOfColumns, AddressRange::MAX_COLUMN_INT)); - return "{$absoluteColumn}{$newColumn}"; + return $absoluteColumn . $newColumn; } protected function updateRowReference(int $newRowIndex, string $absoluteRow): string @@ -126,6 +126,6 @@ class CellReferenceHelper $newRow = $newRowIndex + $this->numberOfRows; $newRow = ($newRow > AddressRange::MAX_ROW) ? AddressRange::MAX_ROW : $newRow; - return "{$absoluteRow}{$newRow}"; + return $absoluteRow . (string) $newRow; } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php index 3d4813468..ade7b99d8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php @@ -52,9 +52,6 @@ class Axis extends Properties /** @var string */ private $axisType = ''; - /** @var ?AxisText */ - private $axisText; - /** * Axis Options. * @@ -91,9 +88,6 @@ class Axis extends Properties Properties::FORMAT_CODE_DATE_ISO8601, ]; - /** @var bool */ - private $noFill = false; - /** * Get Series Data Type. * @@ -189,14 +183,6 @@ class Axis extends Properties */ public function getAxisOptionsProperty($property) { - if ($property === 'textRotation') { - if ($this->axisText !== null) { - if ($this->axisText->getRotation() !== null) { - return (string) $this->axisText->getRotation(); - } - } - } - return $this->axisOptions[$property]; } @@ -309,28 +295,4 @@ class Axis extends Properties return $this; } - - public function getAxisText(): ?AxisText - { - return $this->axisText; - } - - public function setAxisText(?AxisText $axisText): self - { - $this->axisText = $axisText; - - return $this; - } - - public function setNoFill(bool $noFill): self - { - $this->noFill = $noFill; - - return $this; - } - - public function getNoFill(): bool - { - return $this->noFill; - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/AxisText.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/AxisText.php deleted file mode 100644 index cd9ba2ce2..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/AxisText.php +++ /dev/null @@ -1,56 +0,0 @@ -font = new Font(); - $this->font->setSize(null, true); - } - - public function setRotation(?int $rotation): self - { - $this->rotation = $rotation; - - return $this; - } - - public function getRotation(): ?int - { - return $this->rotation; - } - - public function getFillColorObject(): ChartColor - { - $fillColor = $this->font->getChartColor(); - if ($fillColor === null) { - $fillColor = new ChartColor(); - $this->font->setChartColorFromObject($fillColor); - } - - return $fillColor; - } - - public function getFont(): Font - { - return $this->font; - } - - public function setFont(Font $font): self - { - $this->font = $font; - - return $this; - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php index 38c69a463..2ff22a344 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php @@ -150,12 +150,6 @@ class Chart /** @var bool */ private $roundedCorners = false; - /** @var GridLines */ - private $borderLines; - - /** @var ChartColor */ - private $fillColor; - /** * Create a new Chart. * majorGridlines and minorGridlines are deprecated, moved to Axis. @@ -182,8 +176,6 @@ class Chart if ($minorGridlines !== null) { $this->yAxis->setMinorGridlines($minorGridlines); } - $this->fillColor = new ChartColor(); - $this->borderLines = new GridLines(); } /** @@ -794,21 +786,4 @@ class Chart return $this; } - - public function getBorderLines(): GridLines - { - return $this->borderLines; - } - - public function setBorderLines(GridLines $borderLines): self - { - $this->borderLines = $borderLines; - - return $this; - } - - public function getFillColor(): ChartColor - { - return $this->fillColor; - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php index ac36c25c9..0018d79d7 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php @@ -2,8 +2,6 @@ namespace PhpOffice\PhpSpreadsheet\Chart; -use PhpOffice\PhpSpreadsheet\Style\Font; - class Layout { /** @@ -129,11 +127,8 @@ class Layout /** @var ?ChartColor */ private $labelBorderColor; - /** @var ?Font */ - private $labelFont; - - /** @var Properties */ - private $labelEffects; + /** @var ?ChartColor */ + private $labelFontColor; /** * Create a new Layout. @@ -177,18 +172,7 @@ class Layout $this->initBoolean($layout, 'numFmtLinked'); $this->initColor($layout, 'labelFillColor'); $this->initColor($layout, 'labelBorderColor'); - $labelFont = $layout['labelFont'] ?? null; - if ($labelFont instanceof Font) { - $this->labelFont = $labelFont; - } - $labelFontColor = $layout['labelFontColor'] ?? null; - if ($labelFontColor instanceof ChartColor) { - $this->setLabelFontColor($labelFontColor); - } - $labelEffects = $layout['labelEffects'] ?? null; - if ($labelEffects instanceof Properties) { - $this->labelEffects = $labelEffects; - } + $this->initColor($layout, 'labelFontColor'); } private function initBoolean(array $layout, string $name): void @@ -509,32 +493,14 @@ class Layout return $this; } - public function getLabelFont(): ?Font - { - return $this->labelFont; - } - - public function getLabelEffects(): ?Properties - { - return $this->labelEffects; - } - public function getLabelFontColor(): ?ChartColor { - if ($this->labelFont === null) { - return null; - } - - return $this->labelFont->getChartColor(); + return $this->labelFontColor; } public function setLabelFontColor(?ChartColor $chartColor): self { - if ($this->labelFont === null) { - $this->labelFont = new Font(); - $this->labelFont->setSize(null, true); - } - $this->labelFont->setChartColorFromObject($chartColor); + $this->labelFontColor = $chartColor; return $this; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php index 04040aed6..edd87015a 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php @@ -48,15 +48,6 @@ class Legend */ private $layout; - /** @var GridLines */ - private $borderLines; - - /** @var ChartColor */ - private $fillColor; - - /** @var ?AxisText */ - private $legendText; - /** * Create a new Legend. * @@ -69,13 +60,6 @@ class Legend $this->setPosition($position); $this->layout = $layout; $this->setOverlay($overlay); - $this->borderLines = new GridLines(); - $this->fillColor = new ChartColor(); - } - - public function getFillColor(): ChartColor - { - return $this->fillColor; } /** @@ -164,28 +148,4 @@ class Legend { return $this->layout; } - - public function getLegendText(): ?AxisText - { - return $this->legendText; - } - - public function setLegendText(?AxisText $legendText): self - { - $this->legendText = $legendText; - - return $this; - } - - public function getBorderLines(): GridLines - { - return $this->borderLines; - } - - public function setBorderLines(GridLines $borderLines): self - { - $this->borderLines = $borderLines; - - return $this; - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php index 2b78d9a4e..ccde4bb2a 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php @@ -163,49 +163,4 @@ class PlotArea { return $this->gradientFillStops; } - - /** @var ?int */ - private $gapWidth; - - /** @var bool */ - private $useUpBars = false; - - /** @var bool */ - private $useDownBars = false; - - public function getGapWidth(): ?int - { - return $this->gapWidth; - } - - public function setGapWidth(?int $gapWidth): self - { - $this->gapWidth = $gapWidth; - - return $this; - } - - public function getUseUpBars(): bool - { - return $this->useUpBars; - } - - public function setUseUpBars(bool $useUpBars): self - { - $this->useUpBars = $useUpBars; - - return $this; - } - - public function getUseDownBars(): bool - { - return $this->useDownBars; - } - - public function setUseDownBars(bool $useDownBars): self - { - $this->useDownBars = $useDownBars; - - return $this; - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php index d676f1d33..cb9b544b8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php @@ -434,33 +434,12 @@ abstract class JpGraphRendererBase implements IRenderer // Loop through each data series in turn for ($i = 0; $i < $seriesCount; ++$i) { - $plotCategoryByIndex = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i); - if ($plotCategoryByIndex === false) { - $plotCategoryByIndex = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0); - } - $dataValuesY = $plotCategoryByIndex->getDataValues(); + $dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); $dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); - $redoDataValuesY = true; - if ($bubble) { - if (!$bubbleSize) { - $bubbleSize = '10'; - } - $redoDataValuesY = false; - foreach ($dataValuesY as $dataValueY) { - if (!is_int($dataValueY) && !is_float($dataValueY)) { - $redoDataValuesY = true; - - break; - } - } + foreach ($dataValuesY as $k => $dataValueY) { + $dataValuesY[$k] = $k; } - if ($redoDataValuesY) { - foreach ($dataValuesY as $k => $dataValueY) { - $dataValuesY[$k] = $k; - } - } - //var_dump($dataValuesY, $dataValuesX, $bubbleSize); $seriesPlot = new ScatterPlot($dataValuesX, $dataValuesY); if ($scatterStyle == 'lineMarker') { @@ -504,7 +483,7 @@ abstract class JpGraphRendererBase implements IRenderer $dataValues = []; foreach ($dataValuesY as $k => $dataValueY) { - $dataValues[$k] = is_array($dataValueY) ? implode(' ', array_reverse($dataValueY)) : $dataValueY; + $dataValues[$k] = implode(' ', array_reverse($dataValueY)); } $tmp = array_shift($dataValues); $dataValues[] = $tmp; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php index b5e70d3a1..e1f0f90ad 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php @@ -3,12 +3,12 @@ namespace PhpOffice\PhpSpreadsheet\Chart\Renderer; /** - * Jpgraph is not officially maintained by Composer at packagist.org. + * Jpgraph is not oficially maintained in Composer. * * This renderer implementation uses package * https://packagist.org/packages/mitoteam/jpgraph * - * This package is up to date for June 2023 and has PHP 8.2 support. + * This package is up to date for August 2022 and has PHP 8.1 support. */ class MtJpGraphRenderer extends JpGraphRendererBase { @@ -29,7 +29,7 @@ class MtJpGraphRenderer extends JpGraphRendererBase 'regstat', 'scatter', 'stock', - ], true); // enable Extended mode + ]); $loaded = true; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php index 302afee79..afdeea996 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php @@ -107,8 +107,6 @@ class Properties */ private $customProperties = []; - private string $hyperlinkBase = ''; - /** * Create a new Document Properties instance. */ @@ -436,7 +434,7 @@ class Properties * * @param mixed $propertyValue * @param string $propertyType - * 'i' : Integer + * 'i' : Integer * 'f' : Floating Point * 's' : String * 'd' : Date/Time @@ -536,16 +534,4 @@ class Properties { return self::PROPERTY_TYPE_ARRAY[$propertyType] ?? self::PROPERTY_TYPE_UNKNOWN; } - - public function getHyperlinkBase(): string - { - return $this->hyperlinkBase; - } - - public function setHyperlinkBase(string $hyperlinkBase): self - { - $this->hyperlinkBase = $hyperlinkBase; - - return $this; - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Downloader.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Downloader.php deleted file mode 100644 index e66ae4258..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Downloader.php +++ /dev/null @@ -1,89 +0,0 @@ - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xls' => 'application/vnd.ms-excel', - 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', - 'csv' => 'text/csv', - 'html' => 'text/html', - 'pdf' => 'application/pdf', - ]; - - public function __construct(string $folder, string $filename, ?string $filetype = null) - { - if ((is_dir($folder) === false) || (is_readable($folder) === false)) { - throw new Exception("Folder {$folder} is not accessable"); - } - $filepath = "{$folder}/{$filename}"; - $this->filepath = (string) realpath($filepath); - $this->filename = basename($filepath); - if ((file_exists($this->filepath) === false) || (is_readable($this->filepath) === false)) { - throw new Exception("{$this->filename} not found, or cannot be read"); - } - - $filetype ??= pathinfo($filename, PATHINFO_EXTENSION); - if (array_key_exists(strtolower($filetype), self::CONTENT_TYPES) === false) { - throw new Exception("Invalid filetype: {$filetype} cannot be downloaded"); - } - $this->filetype = strtolower($filetype); - } - - public function download(): void - { - $this->headers(); - - readfile($this->filepath); - } - - public function headers(): void - { - ob_clean(); - - $this->contentType(); - $this->contentDisposition(); - $this->cacheHeaders(); - $this->fileSize(); - - flush(); - } - - protected function contentType(): void - { - header('Content-Type: ' . self::CONTENT_TYPES[$this->filetype]); - } - - protected function contentDisposition(): void - { - header('Content-Disposition: attachment;filename="' . $this->filename . '"'); - } - - protected function cacheHeaders(): void - { - header('Cache-Control: max-age=0'); - // If you're serving to IE 9, then the following may be needed - header('Cache-Control: max-age=1'); - - // If you're serving to IE over SSL, then the following may be needed - header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past - header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified - header('Cache-Control: cache, must-revalidate'); // HTTP/1.1 - header('Pragma: public'); // HTTP/1.0 - } - - protected function fileSize(): void - { - header('Content-Length: ' . filesize($this->filepath)); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Handler.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Handler.php deleted file mode 100644 index d05197cef..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Handler.php +++ /dev/null @@ -1,46 +0,0 @@ -attributes; if ($attrs !== null) { @@ -737,72 +737,72 @@ class Html } } - protected function endFontTag(): void + private function endFontTag(): void { $this->face = $this->size = $this->color = null; } - protected function startBoldTag(): void + private function startBoldTag(): void { $this->bold = true; } - protected function endBoldTag(): void + private function endBoldTag(): void { $this->bold = false; } - protected function startItalicTag(): void + private function startItalicTag(): void { $this->italic = true; } - protected function endItalicTag(): void + private function endItalicTag(): void { $this->italic = false; } - protected function startUnderlineTag(): void + private function startUnderlineTag(): void { $this->underline = true; } - protected function endUnderlineTag(): void + private function endUnderlineTag(): void { $this->underline = false; } - protected function startSubscriptTag(): void + private function startSubscriptTag(): void { $this->subscript = true; } - protected function endSubscriptTag(): void + private function endSubscriptTag(): void { $this->subscript = false; } - protected function startSuperscriptTag(): void + private function startSuperscriptTag(): void { $this->superscript = true; } - protected function endSuperscriptTag(): void + private function endSuperscriptTag(): void { $this->superscript = false; } - protected function startStrikethruTag(): void + private function startStrikethruTag(): void { $this->strikethrough = true; } - protected function endStrikethruTag(): void + private function endStrikethruTag(): void { $this->strikethrough = false; } - protected function breakTag(): void + private function breakTag(): void { $this->stringData .= "\n"; } @@ -826,9 +826,8 @@ class Html if (isset($callbacks[$callbackTag])) { $elementHandler = $callbacks[$callbackTag]; if (method_exists($this, $elementHandler)) { - /** @var callable */ - $callable = [$this, $elementHandler]; - call_user_func($callable, $element); + /** @phpstan-ignore-next-line */ + call_user_func([$this, $elementHandler], $element); } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php index 6244375fe..5ca546e07 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php @@ -2,9 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Helper; -use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\IOFactory; -use PhpOffice\PhpSpreadsheet\Settings; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use PhpOffice\PhpSpreadsheet\Writer\IWriter; @@ -14,7 +12,6 @@ use RecursiveRegexIterator; use ReflectionClass; use RegexIterator; use RuntimeException; -use Throwable; /** * Helper class to be used in sample code. @@ -123,7 +120,7 @@ class Sample * @param string $filename * @param string[] $writers */ - public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls'], bool $withCharts = false, ?callable $writerCallback = null): void + public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls']): void { // Set active sheet index to the first sheet, so Excel opens this as the first sheet $spreadsheet->setActiveSheetIndex(0); @@ -132,16 +129,9 @@ class Sample foreach ($writers as $writerType) { $path = $this->getFilename($filename, mb_strtolower($writerType)); $writer = IOFactory::createWriter($spreadsheet, $writerType); - $writer->setIncludeCharts($withCharts); - if ($writerCallback !== null) { - $writerCallback($writer); - } $callStartTime = microtime(true); $writer->save($path); $this->logWrite($writer, $path, /** @scrutinizer ignore-type */ $callStartTime); - if ($this->isCli() === false) { - echo 'Download ' . basename($path) . '
'; - } } $this->logEndingNotes(); @@ -157,7 +147,7 @@ class Sample * * @return string */ - public function getTemporaryFolder() + private function getTemporaryFolder() { $tempFolder = sys_get_temp_dir() . '/phpspreadsheet'; if (!$this->isDirOrMkdir($tempFolder)) { @@ -172,8 +162,10 @@ class Sample * * @param string $filename * @param string $extension + * + * @return string */ - public function getFilename($filename, $extension = 'xlsx'): string + public function getFilename($filename, $extension = 'xlsx') { $originalExtension = pathinfo($filename, PATHINFO_EXTENSION); @@ -203,29 +195,7 @@ class Sample public function log(string $message): void { $eol = $this->isCli() ? PHP_EOL : '
'; - echo($this->isCli() ? date('H:i:s ') : '') . $message . $eol; - } - - public function renderChart(Chart $chart, string $fileName): void - { - if ($this->isCli() === true) { - return; - } - - Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); - - $fileName = $this->getFilename($fileName, 'png'); - - try { - $chart->render($fileName); - $this->log('Rendered image: ' . $fileName); - $imageData = file_get_contents($fileName); - if ($imageData !== false) { - echo '
'; - } - } catch (Throwable $e) { - $this->log('Error rendering chart: ' . $e->getMessage() . PHP_EOL); - } + echo date('H:i:s ') . $message . $eol; } public function titles(string $category, string $functionName, ?string $description = null): void @@ -276,10 +246,7 @@ class Sample $callTime = $callEndTime - $callStartTime; $reflection = new ReflectionClass($writer); $format = $reflection->getShortName(); - - $message = ($this->isCli() === true) - ? "Write {$format} format to {$path} in " . sprintf('%.4f', $callTime) . ' seconds' - : "Write {$format} format to {$path} in " . sprintf('%.4f', $callTime) . ' seconds'; + $message = "Write {$format} format to {$path} in " . sprintf('%.4f', $callTime) . ' seconds'; $this->log($message); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php index 3a4a98f02..ed146a55d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php @@ -48,17 +48,17 @@ class TextGrid public function render(): string { - $this->gridDisplay = $this->isCli ? '' : '
';
+        $this->gridDisplay = $this->isCli ? '' : '';
 
         $maxRow = max($this->rows);
-        $maxRowLength = mb_strlen((string) $maxRow) + 1;
+        $maxRowLength = strlen((string) $maxRow) + 1;
         $columnWidths = $this->getColumnWidths();
 
         $this->renderColumnHeader($maxRowLength, $columnWidths);
         $this->renderRows($maxRowLength, $columnWidths);
         $this->renderFooter($maxRowLength, $columnWidths);
 
-        $this->gridDisplay .= $this->isCli ? '' : '
'; + $this->gridDisplay .= $this->isCli ? '' : ''; return $this->gridDisplay; } @@ -75,9 +75,9 @@ class TextGrid private function renderCells(array $rowData, array $columnWidths): void { foreach ($rowData as $column => $cell) { - $displayCell = ($this->isCli) ? (string) $cell : htmlentities((string) $cell); + $cell = ($this->isCli) ? (string) $cell : htmlentities((string) $cell); $this->gridDisplay .= '| '; - $this->gridDisplay .= $displayCell . str_repeat(' ', $columnWidths[$column] - mb_strlen($cell ?? '') + 1); + $this->gridDisplay .= str_pad($cell, $columnWidths[$column] + 1, ' '); } } @@ -126,12 +126,12 @@ class TextGrid foreach ($columnData as $columnValue) { if (is_string($columnValue)) { - $columnWidth = max($columnWidth, mb_strlen($columnValue)); + $columnWidth = max($columnWidth, strlen($columnValue)); } elseif (is_bool($columnValue)) { - $columnWidth = max($columnWidth, mb_strlen($columnValue ? 'TRUE' : 'FALSE')); + $columnWidth = max($columnWidth, strlen($columnValue ? 'TRUE' : 'FALSE')); } - $columnWidth = max($columnWidth, mb_strlen((string) $columnWidth)); + $columnWidth = max($columnWidth, strlen((string) $columnWidth)); } return $columnWidth; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php index 99e4d6ad6..174553225 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php @@ -80,15 +80,17 @@ class Gnumeric extends BaseReader */ public function canRead(string $filename): bool { - $data = null; - if (File::testFileNoThrow($filename)) { - $data = $this->gzfileGetContents($filename); - if (strpos($data, self::NAMESPACE_GNM) === false) { - $data = ''; + // Check if gzlib functions are available + if (File::testFileNoThrow($filename) && function_exists('gzread')) { + // Read signature data (first 3 bytes) + $fh = fopen($filename, 'rb'); + if ($fh !== false) { + $data = fread($fh, 2); + fclose($fh); } } - return !empty($data); + return isset($data) && $data === chr(0x1F) . chr(0x8B); } private static function matchXml(XMLReader $xml, string $expectedLocalName): bool @@ -108,13 +110,9 @@ class Gnumeric extends BaseReader public function listWorksheetNames($filename) { File::assertFile($filename); - if (!$this->canRead($filename)) { - throw new Exception($filename . ' is an invalid Gnumeric file.'); - } $xml = new XMLReader(); - $contents = $this->gzfileGetContents($filename); - $xml->xml($contents, null, Settings::getLibXmlLoaderOptions()); + $xml->xml($this->getSecurityScannerOrThrow()->scanFile('compress.zlib://' . realpath($filename)), null, Settings::getLibXmlLoaderOptions()); $xml->setParserProperty(2, true); $worksheetNames = []; @@ -141,13 +139,9 @@ class Gnumeric extends BaseReader public function listWorksheetInfo($filename) { File::assertFile($filename); - if (!$this->canRead($filename)) { - throw new Exception($filename . ' is an invalid Gnumeric file.'); - } $xml = new XMLReader(); - $contents = $this->gzfileGetContents($filename); - $xml->xml($contents, null, Settings::getLibXmlLoaderOptions()); + $xml->xml($this->getSecurityScannerOrThrow()->scanFile('compress.zlib://' . realpath($filename)), null, Settings::getLibXmlLoaderOptions()); $xml->setParserProperty(2, true); $worksheetInfo = []; @@ -191,23 +185,13 @@ class Gnumeric extends BaseReader */ private function gzfileGetContents($filename) { + $file = @gzopen($filename, 'rb'); $data = ''; - $contents = @file_get_contents($filename); - if ($contents !== false) { - if (substr($contents, 0, 2) === "\x1f\x8b") { - // Check if gzlib functions are available - if (function_exists('gzdecode')) { - $contents = @gzdecode($contents); - if ($contents !== false) { - $data = $contents; - } - } - } else { - $data = $contents; + if ($file !== false) { + while (!gzeof($file)) { + $data .= gzread($file, 1024); } - } - if ($data !== '') { - $data = $this->getSecurityScannerOrThrow()->scan($data); + gzclose($file); } return $data; @@ -261,13 +245,10 @@ class Gnumeric extends BaseReader { $this->spreadsheet = $spreadsheet; File::assertFile($filename); - if (!$this->canRead($filename)) { - throw new Exception($filename . ' is an invalid Gnumeric file.'); - } $gFileData = $this->gzfileGetContents($filename); - $xml2 = simplexml_load_string($gFileData, 'SimpleXMLElement', Settings::getLibXmlLoaderOptions()); + $xml2 = simplexml_load_string($this->getSecurityScannerOrThrow()->scan($gFileData), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions()); $xml = self::testSimpleXml($xml2); $gnmXML = $xml->children(self::NAMESPACE_GNM); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php index bfb52401a..b165b6c17 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php @@ -7,8 +7,6 @@ use DOMElement; use DOMNode; use DOMText; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; -use PhpOffice\PhpSpreadsheet\Cell\DataType; -use PhpOffice\PhpSpreadsheet\Document\Properties; use PhpOffice\PhpSpreadsheet\Helper\Dimension as CssDimension; use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner; use PhpOffice\PhpSpreadsheet\Spreadsheet; @@ -285,35 +283,15 @@ class Html extends BaseReader * @param int|string $row * @param mixed $cellContent */ - protected function flushCell(Worksheet $sheet, $column, $row, &$cellContent, array $attributeArray): void + protected function flushCell(Worksheet $sheet, $column, $row, &$cellContent): void { if (is_string($cellContent)) { // Simple String content if (trim($cellContent) > '') { // Only actually write it if there's content in the string // Write to worksheet to be done here... - // ... we return the cell, so we can mess about with styles more easily - - // Set cell value explicitly if there is data-type attribute - if (isset($attributeArray['data-type'])) { - $datatype = $attributeArray['data-type']; - if (in_array($datatype, [DataType::TYPE_STRING, DataType::TYPE_STRING2, DataType::TYPE_INLINE])) { - //Prevent to Excel treat string with beginning equal sign or convert big numbers to scientific number - if (substr($cellContent, 0, 1) === '=') { - $sheet->getCell($column . $row) - ->getStyle() - ->setQuotePrefix(true); - } - } - //catching the Exception and ignoring the invalid data types - try { - $sheet->setCellValueExplicit($column . $row, $cellContent, $attributeArray['data-type']); - } catch (\PhpOffice\PhpSpreadsheet\Exception $exception) { - $sheet->setCellValue($column . $row, $cellContent); - } - } else { - $sheet->setCellValue($column . $row, $cellContent); - } + // ... we return the cell so we can mess about with styles more easily + $sheet->setCellValue($column . $row, $cellContent); $this->dataArray[$row][$column] = $cellContent; } } else { @@ -327,7 +305,7 @@ class Html extends BaseReader private function processDomElementBody(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child): void { $attributeArray = []; - foreach ($child->attributes as $attribute) { + foreach (($child->attributes ?? []) as $attribute) { $attributeArray[$attribute->name] = $attribute->value; } @@ -377,7 +355,7 @@ class Html extends BaseReader private function processDomElementHr(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void { if ($child->nodeName === 'hr') { - $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); + $this->flushCell($sheet, $column, $row, $cellContent); ++$row; if (isset($this->formats[$child->nodeName])) { $sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]); @@ -397,7 +375,7 @@ class Html extends BaseReader $sheet->getStyle($column . $row)->getAlignment()->setWrapText(true); } else { // Otherwise flush our existing content and move the row cursor on - $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); + $this->flushCell($sheet, $column, $row, $cellContent); ++$row; } } else { @@ -443,11 +421,11 @@ class Html extends BaseReader $this->processDomElement($child, $sheet, $row, $column, $cellContent); } else { if ($cellContent > '') { - $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); + $this->flushCell($sheet, $column, $row, $cellContent); ++$row; } $this->processDomElement($child, $sheet, $row, $column, $cellContent); - $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); + $this->flushCell($sheet, $column, $row, $cellContent); if (isset($this->formats[$child->nodeName])) { $sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]); @@ -470,11 +448,11 @@ class Html extends BaseReader $this->processDomElement($child, $sheet, $row, $column, $cellContent); } else { if ($cellContent > '') { - $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); + $this->flushCell($sheet, $column, $row, $cellContent); } ++$row; $this->processDomElement($child, $sheet, $row, $column, $cellContent); - $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); + $this->flushCell($sheet, $column, $row, $cellContent); $column = 'A'; } } else { @@ -491,13 +469,10 @@ class Html extends BaseReader } } - private string $currentColumn = 'A'; - private function processDomElementTable(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void { if ($child->nodeName === 'table') { - $this->currentColumn = 'A'; - $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); + $this->flushCell($sheet, $column, $row, $cellContent); $column = $this->setTableStartColumn($column); if ($this->tableLevel > 1 && $row > 1) { --$row; @@ -516,10 +491,7 @@ class Html extends BaseReader private function processDomElementTr(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void { - if ($child->nodeName === 'col') { - $this->applyInlineStyle($sheet, -1, $this->currentColumn, $attributeArray); - ++$this->currentColumn; - } elseif ($child->nodeName === 'tr') { + if ($child->nodeName === 'tr') { $column = $this->getTableStartColumn(); $cellContent = ''; $this->processDomElement($child, $sheet, $row, $column, $cellContent); @@ -602,7 +574,7 @@ class Html extends BaseReader // apply inline style $this->applyInlineStyle($sheet, $row, $column, $attributeArray); - $this->flushCell($sheet, $column, $row, $cellContent, $attributeArray); + $this->flushCell($sheet, $column, $row, $cellContent); $this->processDomElementBgcolor($sheet, $row, $column, $attributeArray); $this->processDomElementWidth($sheet, $column, $attributeArray); @@ -692,94 +664,10 @@ class Html extends BaseReader if ($loaded === false) { throw new Exception('Failed to load ' . $filename . ' as a DOM Document', 0, $e ?? null); } - self::loadProperties($dom, $spreadsheet); return $this->loadDocument($dom, $spreadsheet); } - private static function loadProperties(DOMDocument $dom, Spreadsheet $spreadsheet): void - { - $properties = $spreadsheet->getProperties(); - foreach ($dom->getElementsByTagName('meta') as $meta) { - $metaContent = (string) $meta->getAttribute('content'); - if ($metaContent !== '') { - $metaName = (string) $meta->getAttribute('name'); - switch ($metaName) { - case 'author': - $properties->setCreator($metaContent); - - break; - case 'category': - $properties->setCategory($metaContent); - - break; - case 'company': - $properties->setCompany($metaContent); - - break; - case 'created': - $properties->setCreated($metaContent); - - break; - case 'description': - $properties->setDescription($metaContent); - - break; - case 'keywords': - $properties->setKeywords($metaContent); - - break; - case 'lastModifiedBy': - $properties->setLastModifiedBy($metaContent); - - break; - case 'manager': - $properties->setManager($metaContent); - - break; - case 'modified': - $properties->setModified($metaContent); - - break; - case 'subject': - $properties->setSubject($metaContent); - - break; - case 'title': - $properties->setTitle($metaContent); - - break; - default: - if (preg_match('/^custom[.](bool|date|float|int|string)[.](.+)$/', $metaName, $matches) === 1) { - switch ($matches[1]) { - case 'bool': - $properties->setCustomProperty($matches[2], (bool) $metaContent, Properties::PROPERTY_TYPE_BOOLEAN); - - break; - case 'float': - $properties->setCustomProperty($matches[2], (float) $metaContent, Properties::PROPERTY_TYPE_FLOAT); - - break; - case 'int': - $properties->setCustomProperty($matches[2], (int) $metaContent, Properties::PROPERTY_TYPE_INTEGER); - - break; - case 'date': - $properties->setCustomProperty($matches[2], $metaContent, Properties::PROPERTY_TYPE_DATE); - - break; - default: // string - $properties->setCustomProperty($matches[2], $metaContent, Properties::PROPERTY_TYPE_STRING); - } - } - } - } - } - if (!empty($dom->baseURI)) { - $properties->setHyperlinkBase($dom->baseURI); - } - } - private static function replaceNonAscii(array $matches): string { return '&#' . mb_ord($matches[0], 'UTF-8') . ';'; @@ -810,10 +698,8 @@ class Html extends BaseReader if ($loaded === false) { throw new Exception('Failed to load content as a DOM Document', 0, $e ?? null); } - $spreadsheet = $spreadsheet ?? new Spreadsheet(); - self::loadProperties($dom, $spreadsheet); - return $this->loadDocument($dom, $spreadsheet); + return $this->loadDocument($dom, $spreadsheet ?? new Spreadsheet()); } /** @@ -883,9 +769,7 @@ class Html extends BaseReader return; } - if ($row <= 0 || $column === '') { - $cellStyle = new Style(); - } elseif (isset($attributeArray['rowspan'], $attributeArray['colspan'])) { + if (isset($attributeArray['rowspan'], $attributeArray['colspan'])) { $columnTo = $column; for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) { ++$columnTo; @@ -1017,20 +901,16 @@ class Html extends BaseReader break; case 'width': - if ($column !== '') { - $sheet->getColumnDimension($column)->setWidth( - (new CssDimension($styleValue ?? ''))->width() - ); - } + $sheet->getColumnDimension($column)->setWidth( + (new CssDimension($styleValue ?? ''))->width() + ); break; case 'height': - if ($row > 0) { - $sheet->getRowDimension($row)->setRowHeight( - (new CssDimension($styleValue ?? ''))->height() - ); - } + $sheet->getRowDimension($row)->setRowHeight( + (new CssDimension($styleValue ?? ''))->height() + ); break; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php index 9913f3325..250815400 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php @@ -8,7 +8,6 @@ use DOMElement; use DOMNode; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\DataType; -use PhpOffice\PhpSpreadsheet\Helper\Dimension as HelperDimension; use PhpOffice\PhpSpreadsheet\Reader\Ods\AutoFilter; use PhpOffice\PhpSpreadsheet\Reader\Ods\DefinedNames; use PhpOffice\PhpSpreadsheet\Reader\Ods\FormulaTranslator; @@ -296,29 +295,11 @@ class Ods extends BaseReader $tableNs = $dom->lookupNamespaceUri('table'); $textNs = $dom->lookupNamespaceUri('text'); $xlinkNs = $dom->lookupNamespaceUri('xlink'); - $styleNs = $dom->lookupNamespaceUri('style'); $pageSettings->readStyleCrossReferences($dom); $autoFilterReader = new AutoFilter($spreadsheet, $tableNs); $definedNameReader = new DefinedNames($spreadsheet, $tableNs); - $columnWidths = []; - $automaticStyle0 = $dom->getElementsByTagNameNS($officeNs, 'automatic-styles')->item(0); - $automaticStyles = ($automaticStyle0 === null) ? [] : $automaticStyle0->getElementsByTagNameNS($styleNs, 'style'); - foreach ($automaticStyles as $automaticStyle) { - $styleName = $automaticStyle->getAttributeNS($styleNs, 'name'); - $styleFamily = $automaticStyle->getAttributeNS($styleNs, 'family'); - if ($styleFamily === 'table-column') { - $tcprops = $automaticStyle->getElementsByTagNameNS($styleNs, 'table-column-properties'); - if ($tcprops !== null) { - $tcprop = $tcprops->item(0); - if ($tcprop !== null) { - $columnWidth = $tcprop->getAttributeNs($styleNs, 'column-width'); - $columnWidths[$styleName] = $columnWidth; - } - } - } - } // Content $item0 = $dom->getElementsByTagNameNS($officeNs, 'body')->item(0); @@ -359,7 +340,6 @@ class Ods extends BaseReader // Go through every child of table element $rowID = 1; - $tableColumnIndex = 1; foreach ($worksheetDataSet->childNodes as $childNode) { /** @var DOMElement $childNode */ @@ -386,26 +366,6 @@ class Ods extends BaseReader // $rowData = $cellData; // break; // } - break; - case 'table-column': - if ($childNode->hasAttributeNS($tableNs, 'number-columns-repeated')) { - $rowRepeats = (int) $childNode->getAttributeNS($tableNs, 'number-columns-repeated'); - } else { - $rowRepeats = 1; - } - $tableStyleName = $childNode->getAttributeNS($tableNs, 'style-name'); - if (isset($columnWidths[$tableStyleName])) { - $columnWidth = new HelperDimension($columnWidths[$tableStyleName]); - $tableColumnString = Coordinate::stringFromColumnIndex($tableColumnIndex); - for ($rowRepeats2 = $rowRepeats; $rowRepeats2 > 0; --$rowRepeats2) { - $spreadsheet->getActiveSheet() - ->getColumnDimension($tableColumnString) - ->setWidth($columnWidth->toUnit('cm'), 'cm'); - ++$tableColumnString; - } - } - $tableColumnIndex += $rowRepeats; - break; case 'table-row': if ($childNode->hasAttributeNS($tableNs, 'number-rows-repeated')) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php index f8eaf39d0..ad898ae41 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php @@ -151,7 +151,7 @@ class XmlScanner throw new Reader\Exception('Detected use of ENTITY in XML, spreadsheet file load() aborted to prevent XXE/XEE attacks'); } - if ($this->callback !== null) { + if ($this->callback !== null && is_callable($this->callback)) { $xml = call_user_func($this->callback, $xml); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php index 816e7698d..f35e8c3b2 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php @@ -430,7 +430,7 @@ class Xls extends BaseReader */ public function canRead(string $filename): bool { - if (File::testFileNoThrow($filename) === false) { + if (!File::testFileNoThrow($filename)) { return false; } @@ -440,9 +440,6 @@ class Xls extends BaseReader // get excel data $ole->read($filename); - if ($ole->wrkbook === null) { - throw new Exception('The filename ' . $filename . ' is not recognised as a Spreadsheet file'); - } return true; } catch (PhpSpreadsheetException $e) { @@ -452,7 +449,7 @@ class Xls extends BaseReader public function setCodepage(string $codepage): void { - if (CodePage::validate($codepage) === false) { + if (!CodePage::validate($codepage)) { throw new PhpSpreadsheetException('Unknown codepage: ' . $codepage); } @@ -1100,7 +1097,7 @@ class Xls extends BaseReader // treat OBJ records foreach ($this->objs as $n => $obj) { // the first shape container never has a corresponding OBJ record, hence $n + 1 - if (isset($allSpContainers[$n + 1])) { + if (isset($allSpContainers[$n + 1]) && is_object($allSpContainers[$n + 1])) { $spContainer = $allSpContainers[$n + 1]; // we skip all spContainers that are a part of a group shape since we cannot yet handle those diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php index 1c33fd681..bf8908470 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php @@ -16,7 +16,6 @@ use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Hyperlinks; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\PageSetup; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Properties as PropertyReader; -use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SharedFormula; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViewOptions; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViews; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Styles; @@ -62,11 +61,6 @@ class Xlsx extends BaseReader /** @var Styles */ private $styleReader; - /** - * @var array - */ - private $sharedFormulae = []; - /** * Create a new Xlsx Reader instance. */ @@ -134,7 +128,7 @@ class Xlsx extends BaseReader if ($replaceUnclosedBr) { $contents = str_replace('
', '
', $contents); } - $rels = @simplexml_load_string( + $rels = simplexml_load_string( $this->getSecurityScannerOrThrow()->scan($contents), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions(), @@ -252,7 +246,6 @@ class Xlsx extends BaseReader $xmlWorkbook = $this->loadZip($relTarget, $mainNS); if ($xmlWorkbook->sheets) { $dir = dirname($relTarget); - /** @var SimpleXMLElement $eleSheet */ foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { $tmpInfo = [ @@ -268,8 +261,8 @@ class Xlsx extends BaseReader $xml = new XMLReader(); $xml->xml( - $this->getSecurityScannerOrThrow()->scan( - $this->getFromZipArchive($this->zip, $fileWorksheetPath) + $this->getSecurityScannerOrThrow()->scanFile( + 'zip://' . File::realpath($filename) . '#' . $fileWorksheetPath ), null, Settings::getLibXmlLoaderOptions() @@ -331,13 +324,13 @@ class Xlsx extends BaseReader * @param mixed $value * @param mixed $calculatedValue */ - private function castToFormula(?SimpleXMLElement $c, string $r, string &$cellDataType, &$value, &$calculatedValue, string $castBaseType, bool $updateSharedCells = true): void + private function castToFormula(?SimpleXMLElement $c, string $r, string &$cellDataType, &$value, &$calculatedValue, array &$sharedFormulas, string $castBaseType): void { if ($c === null) { return; } $attr = $c->f->attributes(); - $cellDataType = DataType::TYPE_FORMULA; + $cellDataType = 'f'; $value = "={$c->f}"; $calculatedValue = self::$castBaseType($c); @@ -345,19 +338,17 @@ class Xlsx extends BaseReader if (isset($attr['t']) && strtolower((string) $attr['t']) == 'shared') { $instance = (string) $attr['si']; - if (!isset($this->sharedFormulae[(string) $attr['si']])) { - $this->sharedFormulae[$instance] = new SharedFormula($r, $value); - } elseif ($updateSharedCells === true) { - // It's only worth the overhead of adjusting the shared formula for this cell if we're actually loading - // the cell, which may not be the case if we're using a read filter. - $master = Coordinate::indexesFromString($this->sharedFormulae[$instance]->master()); + if (!isset($sharedFormulas[(string) $attr['si']])) { + $sharedFormulas[$instance] = ['master' => $r, 'formula' => $value]; + } else { + $master = Coordinate::indexesFromString($sharedFormulas[$instance]['master']); $current = Coordinate::indexesFromString($r); $difference = [0, 0]; $difference[0] = $current[0] - $master[0]; $difference[1] = $current[1] - $master[1]; - $value = $this->referenceHelper->updateFormulaReferences($this->sharedFormulae[$instance]->formula(), 'A1', $difference[0], $difference[1]); + $value = $this->referenceHelper->updateFormulaReferences($sharedFormulas[$instance]['formula'], 'A1', $difference[0], $difference[1]); } } } @@ -404,18 +395,12 @@ class Xlsx extends BaseReader // Sadly, some 3rd party xlsx generators don't use consistent case for filenaming // so we need to load case-insensitively from the zip file - $contents = $archive->getFromName($fileName, 0, ZipArchive::FL_NOCASE); - // Apache POI fixes + $contents = $archive->getFromName($fileName, 0, ZipArchive::FL_NOCASE); if ($contents === false) { $contents = $archive->getFromName(substr($fileName, 1), 0, ZipArchive::FL_NOCASE); } - // Has the file been saved with Windoze directory separators rather than unix? - if ($contents === false) { - $contents = $archive->getFromName(str_replace('/', '\\', $fileName), 0, ZipArchive::FL_NOCASE); - } - return ($contents === false) ? '' : $contents; } @@ -462,7 +447,6 @@ class Xlsx extends BaseReader $colourScheme = self::getAttributes($xmlTheme->themeElements->clrScheme); $colourSchemeName = (string) $colourScheme['name']; - $excel->getTheme()->setThemeColorName($colourSchemeName); $colourScheme = $xmlTheme->themeElements->clrScheme->children($drawingNS); $themeColours = []; @@ -474,46 +458,14 @@ class Xlsx extends BaseReader if (isset($xmlColour->sysClr)) { $xmlColourData = self::getAttributes($xmlColour->sysClr); $themeColours[$themePos] = (string) $xmlColourData['lastClr']; - $excel->getTheme()->setThemeColor($k, (string) $xmlColourData['lastClr']); } elseif (isset($xmlColour->srgbClr)) { $xmlColourData = self::getAttributes($xmlColour->srgbClr); $themeColours[$themePos] = (string) $xmlColourData['val']; - $excel->getTheme()->setThemeColor($k, (string) $xmlColourData['val']); } } $theme = new Theme($themeName, $colourSchemeName, $themeColours); $this->styleReader->setTheme($theme); - $fontScheme = self::getAttributes($xmlTheme->themeElements->fontScheme); - $fontSchemeName = (string) $fontScheme['name']; - $excel->getTheme()->setThemeFontName($fontSchemeName); - $majorFonts = []; - $minorFonts = []; - $fontScheme = $xmlTheme->themeElements->fontScheme->children($drawingNS); - $majorLatin = self::getAttributes($fontScheme->majorFont->latin)['typeface'] ?? ''; - $majorEastAsian = self::getAttributes($fontScheme->majorFont->ea)['typeface'] ?? ''; - $majorComplexScript = self::getAttributes($fontScheme->majorFont->cs)['typeface'] ?? ''; - $minorLatin = self::getAttributes($fontScheme->minorFont->latin)['typeface'] ?? ''; - $minorEastAsian = self::getAttributes($fontScheme->minorFont->ea)['typeface'] ?? ''; - $minorComplexScript = self::getAttributes($fontScheme->minorFont->cs)['typeface'] ?? ''; - - foreach ($fontScheme->majorFont->font as $xmlFont) { - $fontAttributes = self::getAttributes($xmlFont); - $script = (string) ($fontAttributes['script'] ?? ''); - if (!empty($script)) { - $majorFonts[$script] = (string) ($fontAttributes['typeface'] ?? ''); - } - } - foreach ($fontScheme->minorFont->font as $xmlFont) { - $fontAttributes = self::getAttributes($xmlFont); - $script = (string) ($fontAttributes['script'] ?? ''); - if (!empty($script)) { - $minorFonts[$script] = (string) ($fontAttributes['typeface'] ?? ''); - } - } - $excel->getTheme()->setMajorFontValues($majorLatin, $majorEastAsian, $majorComplexScript, $majorFonts); - $excel->getTheme()->setMinorFontValues($minorLatin, $minorEastAsian, $minorComplexScript, $minorFonts); - break; } } @@ -525,10 +477,6 @@ class Xlsx extends BaseReader foreach ($rels->Relationship as $relx) { $rel = self::getAttributes($relx); $relTarget = (string) $rel['Target']; - // issue 3553 - if ($relTarget[0] === '/') { - $relTarget = substr($relTarget, 1); - } $relType = (string) $rel['Type']; $mainNS = self::REL_TO_MAIN[$relType] ?? Namespaces::MAIN; switch ($relType) { @@ -559,6 +507,26 @@ class Xlsx extends BaseReader $relsWorkbook = $this->loadZip("$dir/_rels/" . basename($relTarget) . '.rels', ''); $relsWorkbook->registerXPathNamespace('rel', Namespaces::RELATIONSHIPS); + $sharedStrings = []; + $relType = "rel:Relationship[@Type='" + //. Namespaces::SHARED_STRINGS + . "$xmlNamespaceBase/sharedStrings" + . "']"; + $xpath = self::getArrayItem($relsWorkbook->xpath($relType)); + + if ($xpath) { + $xmlStrings = $this->loadZip("$dir/$xpath[Target]", $mainNS); + if (isset($xmlStrings->si)) { + foreach ($xmlStrings->si as $val) { + if (isset($val->t)) { + $sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t); + } elseif (isset($val->r)) { + $sharedStrings[] = $this->parseRichText($val); + } + } + } + } + $worksheets = []; $macros = $customUI = null; foreach ($relsWorkbook->Relationship as $elex) { @@ -650,7 +618,7 @@ class Xlsx extends BaseReader $numFmt = NumberFormat::builtInFormatCode((int) $xf['numFmtId']); } } - $quotePrefix = (bool) (string) ($xf['quotePrefix'] ?? ''); + $quotePrefix = (bool) ($xf['quotePrefix'] ?? false); $style = (object) [ 'numFmt' => $numFmt ?? NumberFormat::FORMAT_GENERAL, @@ -685,7 +653,7 @@ class Xlsx extends BaseReader } } - $quotePrefix = (bool) (string) ($xf['quotePrefix'] ?? ''); + $quotePrefix = (bool) ($xf['quotePrefix'] ?? false); $cellStyle = (object) [ 'numFmt' => $numFmt, @@ -714,27 +682,6 @@ class Xlsx extends BaseReader $dxfs = $this->styleReader->dxfs($this->readDataOnly); $styles = $this->styleReader->styles(); - // Read content after setting the styles - $sharedStrings = []; - $relType = "rel:Relationship[@Type='" - //. Namespaces::SHARED_STRINGS - . "$xmlNamespaceBase/sharedStrings" - . "']"; - $xpath = self::getArrayItem($relsWorkbook->xpath($relType)); - - if ($xpath) { - $xmlStrings = $this->loadZip("$dir/$xpath[Target]", $mainNS); - if (isset($xmlStrings->si)) { - foreach ($xmlStrings->si as $val) { - if (isset($val->t)) { - $sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t); - } elseif (isset($val->r)) { - $sharedStrings[] = $this->parseRichText($val); - } - } - } - } - $xmlWorkbook = $this->loadZipNoNamespace($relTarget, $mainNS); $xmlWorkbookNS = $this->loadZip($relTarget, $mainNS); @@ -796,8 +743,7 @@ class Xlsx extends BaseReader $xmlSheet = $this->loadZipNoNamespace("$dir/$fileWorksheet", $mainNS); $xmlSheetNS = $this->loadZip("$dir/$fileWorksheet", $mainNS); - // Shared Formula table is unique to each Worksheet, so we need to reset it here - $this->sharedFormulae = []; + $sharedFormulas = []; if (isset($eleSheetAttr['state']) && (string) $eleSheetAttr['state'] != '') { $docSheet->setSheetState((string) $eleSheetAttr['state']); @@ -843,12 +789,8 @@ class Xlsx extends BaseReader $coordinates = Coordinate::coordinateFromString($r); if (!$this->getReadFilter()->readCell($coordinates[0], (int) $coordinates[1], $docSheet->getTitle())) { - // Normally, just testing for the f attribute should identify this cell as containing a formula - // that we need to read, even though it is outside of the filter range, in case it is a shared formula. - // But in some cases, this attribute isn't set; so we need to delve a level deeper and look at - // whether or not the cell has a child formula element that is shared. - if (isset($cAttr->f) || (isset($c->f, $c->f->attributes()['t']) && strtolower((string) $c->f->attributes()['t']) === 'shared')) { - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToError', false); + if (isset($cAttr->f)) { + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError'); } ++$rowIndex; @@ -880,7 +822,7 @@ class Xlsx extends BaseReader } } else { // Formula - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToBoolean'); + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToBoolean'); if (isset($c->f['t'])) { $att = $c->f; $docSheet->getCell($r)->setFormulaAttributes($att); @@ -890,7 +832,7 @@ class Xlsx extends BaseReader break; case 'inlineStr': if (isset($c->f)) { - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToError'); + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError'); } else { $value = $this->parseRichText($c->is); } @@ -901,7 +843,7 @@ class Xlsx extends BaseReader $value = self::castToError($c); } else { // Formula - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToError'); + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError'); } break; @@ -910,7 +852,7 @@ class Xlsx extends BaseReader $value = self::castToString($c); } else { // Formula - $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToString'); + $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToString'); if (isset($c->f['t'])) { $attributes = $c->f['t']; $docSheet->getCell($r)->setFormulaAttributes(['t' => (string) $attributes]); @@ -949,10 +891,6 @@ class Xlsx extends BaseReader // no style index means 0, it seems $cell->setXfIndex(isset($styles[(int) ($cAttr['s'])]) ? (int) ($cAttr['s']) : 0); - // issue 3495 - if ($cell->getDataType() === DataType::TYPE_FORMULA) { - $cell->getStyle()->setQuotePrefix(false); - } } } ++$rowIndex; @@ -960,12 +898,6 @@ class Xlsx extends BaseReader ++$cIndex; } } - if ($xmlSheetNS && $xmlSheetNS->ignoredErrors) { - foreach ($xmlSheetNS->ignoredErrors->ignoredError as $ignoredErrorx) { - $ignoredError = self::testSimpleXml($ignoredErrorx); - $this->processIgnoredErrors($ignoredError, $docSheet); - } - } if (!$this->readDataOnly && $xmlSheetNS && $xmlSheetNS->sheetProtection) { $protAttr = $xmlSheetNS->sheetProtection->attributes() ?? []; @@ -2273,48 +2205,4 @@ class Xlsx extends BaseReader return $array; } - - private function processIgnoredErrors(SimpleXMLElement $xml, Worksheet $sheet): void - { - $attributes = self::getAttributes($xml); - $sqref = (string) ($attributes['sqref'] ?? ''); - $numberStoredAsText = (string) ($attributes['numberStoredAsText'] ?? ''); - $formula = (string) ($attributes['formula'] ?? ''); - $twoDigitTextYear = (string) ($attributes['twoDigitTextYear'] ?? ''); - $evalError = (string) ($attributes['evalError'] ?? ''); - if (!empty($sqref)) { - $explodedSqref = explode(' ', $sqref); - $pattern1 = '/^([A-Z]{1,3})([0-9]{1,7})(:([A-Z]{1,3})([0-9]{1,7}))?$/'; - foreach ($explodedSqref as $sqref1) { - if (preg_match($pattern1, $sqref1, $matches) === 1) { - $firstRow = $matches[2]; - $firstCol = $matches[1]; - if (array_key_exists(3, $matches)) { - $lastCol = $matches[4]; - $lastRow = $matches[5]; - } else { - $lastCol = $firstCol; - $lastRow = $firstRow; - } - ++$lastCol; - for ($row = $firstRow; $row <= $lastRow; ++$row) { - for ($col = $firstCol; $col !== $lastCol; ++$col) { - if ($numberStoredAsText === '1') { - $sheet->getCell("$col$row")->getIgnoredErrors()->setNumberStoredAsText(true); - } - if ($formula === '1') { - $sheet->getCell("$col$row")->getIgnoredErrors()->setFormula(true); - } - if ($twoDigitTextYear === '1') { - $sheet->getCell("$col$row")->getIgnoredErrors()->setTwoDigitTextYear(true); - } - if ($evalError === '1') { - $sheet->getCell("$col$row")->getIgnoredErrors()->setEvalError(true); - } - } - } - } - } - } - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index c5a59f558..5230cf0d7 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -4,7 +4,6 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx; use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError; use PhpOffice\PhpSpreadsheet\Chart\Axis; -use PhpOffice\PhpSpreadsheet\Chart\AxisText; use PhpOffice\PhpSpreadsheet\Chart\ChartColor; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; @@ -77,28 +76,16 @@ class Chart $yAxis = new Axis(); $autoTitleDeleted = null; $chartNoFill = false; - $chartBorderLines = null; - $chartFillColor = null; $gradientArray = []; $gradientLin = null; $roundedCorners = false; - $gapWidth = null; - $useUpBars = null; - $useDownBars = null; foreach ($chartElementsC as $chartElementKey => $chartElement) { switch ($chartElementKey) { case 'spPr': - $children = $chartElementsC->spPr->children($this->aNamespace); - if (isset($children->noFill)) { + $possibleNoFill = $chartElementsC->spPr->children($this->aNamespace); + if (isset($possibleNoFill->noFill)) { $chartNoFill = true; } - if (isset($children->solidFill)) { - $chartFillColor = $this->readColor($children->solidFill); - } - if (isset($children->ln)) { - $chartBorderLines = new GridLines(); - $this->readLineStyle($chartElementsC, $chartBorderLines); - } break; case 'roundedCorners': @@ -170,9 +157,6 @@ class Chart $axisColorArray = $this->readColor($sppr->solidFill); $xAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); } - if (isset($chartDetail->spPr->ln->noFill)) { - $xAxis->setNoFill(true); - } } if (isset($chartDetail->majorGridlines)) { $majorGridlines = new GridLines(); @@ -243,9 +227,6 @@ class Chart $axisColorArray = $this->readColor($sppr->solidFill); $whichAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); } - if (isset($sppr->ln->noFill)) { - $whichAxis->setNoFill(true); - } } if ($whichAxis !== null && isset($chartDetail->majorGridlines)) { $majorGridlines = new GridLines(); @@ -335,15 +316,6 @@ class Chart break; case 'stockChart': $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); - if (isset($chartDetail->upDownBars->gapWidth)) { - $gapWidth = self::getAttribute($chartDetail->upDownBars->gapWidth, 'val', 'integer'); - } - if (isset($chartDetail->upDownBars->upBars)) { - $useUpBars = true; - } - if (isset($chartDetail->upDownBars->downBars)) { - $useDownBars = true; - } $plotAttributes = $this->readChartAttributes($chartDetail); break; @@ -360,15 +332,6 @@ class Chart if (!empty($gradientArray)) { $plotArea->setGradientFillProperties($gradientArray, $gradientLin); } - if (is_int($gapWidth)) { - $plotArea->setGapWidth($gapWidth); - } - if ($useUpBars === true) { - $plotArea->setUseUpBars(true); - } - if ($useDownBars === true) { - $plotArea->setUseDownBars(true); - } break; case 'plotVisOnly': @@ -387,10 +350,6 @@ class Chart $legendPos = 'r'; $legendLayout = null; $legendOverlay = false; - $legendBorderLines = null; - $legendFillColor = null; - $legendText = null; - $addLegendText = false; foreach ($chartDetails as $chartDetailKey => $chartDetail) { $chartDetail = Xlsx::testSimpleXml($chartDetail); switch ($chartDetailKey) { @@ -405,45 +364,10 @@ class Chart case 'layout': $legendLayout = $this->chartLayoutDetails($chartDetail); - break; - case 'spPr': - $children = $chartDetails->spPr->children($this->aNamespace); - if (isset($children->solidFill)) { - $legendFillColor = $this->readColor($children->solidFill); - } - if (isset($children->ln)) { - $legendBorderLines = new GridLines(); - $this->readLineStyle($chartDetails, $legendBorderLines); - } - - break; - case 'txPr': - $children = $chartDetails->txPr->children($this->aNamespace); - $addLegendText = false; - $legendText = new AxisText(); - if (isset($children->p->pPr->defRPr->solidFill)) { - $colorArray = $this->readColor($children->p->pPr->defRPr->solidFill); - $legendText->getFillColorObject()->setColorPropertiesArray($colorArray); - $addLegendText = true; - } - if (isset($children->p->pPr->defRPr->effectLst)) { - $this->readEffects($children->p->pPr->defRPr, $legendText, false); - $addLegendText = true; - } - break; } } $legend = new Legend("$legendPos", $legendLayout, (bool) $legendOverlay); - if ($legendFillColor !== null) { - $legend->getFillColor()->setColorPropertiesArray($legendFillColor); - } - if ($legendBorderLines !== null) { - $legend->setBorderLines($legendBorderLines); - } - if ($addLegendText) { - $legend->setLegendText($legendText); - } break; } @@ -454,12 +378,6 @@ class Chart if ($chartNoFill) { $chart->setNoFill(true); } - if ($chartFillColor !== null) { - $chart->getFillColor()->setColorPropertiesArray($chartFillColor); - } - if ($chartBorderLines !== null) { - $chart->setBorderLines($chartBorderLines); - } $chart->setRoundedCorners($roundedCorners); if (is_bool($autoTitleDeleted)) { $chart->setAutoTitleDeleted($autoTitleDeleted); @@ -1164,37 +1082,6 @@ class Chart return $value; } - private function parseFont(SimpleXMLElement $titleDetailPart): ?Font - { - if (!isset($titleDetailPart->pPr->defRPr)) { - return null; - } - $fontArray = []; - $fontArray['size'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'sz', 'integer'); - $fontArray['bold'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'b', 'boolean'); - $fontArray['italic'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'i', 'boolean'); - $fontArray['underscore'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'u', 'string'); - $fontArray['strikethrough'] = self::getAttribute($titleDetailPart->pPr->defRPr, 'strike', 'string'); - - if (isset($titleDetailPart->pPr->defRPr->latin)) { - $fontArray['latin'] = self::getAttribute($titleDetailPart->pPr->defRPr->latin, 'typeface', 'string'); - } - if (isset($titleDetailPart->pPr->defRPr->ea)) { - $fontArray['eastAsian'] = self::getAttribute($titleDetailPart->pPr->defRPr->ea, 'typeface', 'string'); - } - if (isset($titleDetailPart->pPr->defRPr->cs)) { - $fontArray['complexScript'] = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string'); - } - if (isset($titleDetailPart->pPr->defRPr->solidFill)) { - $fontArray['chartColor'] = new ChartColor($this->readColor($titleDetailPart->pPr->defRPr->solidFill)); - } - $font = new Font(); - $font->setSize(null, true); - $font->applyFromArray($fontArray); - - return $font; - } - /** * @param ?SimpleXMLElement $chartDetail */ @@ -1241,13 +1128,8 @@ class Chart } if (isset($chartDetail->dLbls->txPr)) { $txpr = $chartDetail->dLbls->txPr->children($this->aNamespace); - if (isset($txpr->p)) { - $plotAttributes['labelFont'] = $this->parseFont($txpr->p); - if (isset($txpr->p->pPr->defRPr->effectLst)) { - $labelEffects = new GridLines(); - $this->readEffects($txpr->p->pPr->defRPr, $labelEffects, false); - $plotAttributes['labelEffects'] = $labelEffects; - } + if (isset($txpr->p->pPr->defRPr->solidFill)) { + $plotAttributes['labelFontColor'] = new ChartColor($this->readColor($txpr->p->pPr->defRPr->solidFill)); } } } @@ -1294,19 +1176,13 @@ class Chart } } - private function readEffects(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject, bool $getSppr = true): void + private function readEffects(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject): void { - if (!isset($chartObject)) { + if (!isset($chartObject, $chartDetail->spPr)) { return; } - if ($getSppr) { - if (!isset($chartDetail->spPr)) { - return; - } - $sppr = $chartDetail->spPr->children($this->aNamespace); - } else { - $sppr = $chartDetail; - } + $sppr = $chartDetail->spPr->children($this->aNamespace); + if (isset($sppr->effectLst->glow)) { $axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / ChartProperties::POINTS_WIDTH_MULTIPLIER; if ($axisGlowSize != 0.0) { @@ -1536,30 +1412,13 @@ class Chart } if (isset($chartDetail->txPr)) { $children = $chartDetail->txPr->children($this->aNamespace); - $addAxisText = false; - $axisText = new AxisText(); if (isset($children->bodyPr)) { /** @var string */ $textRotation = self::getAttribute($children->bodyPr, 'rot', 'string'); if (is_numeric($textRotation)) { - $axisText->setRotation((int) ChartProperties::xmlToAngle($textRotation)); - $addAxisText = true; + $whichAxis->setAxisOption('textRotation', (string) ChartProperties::xmlToAngle($textRotation)); } } - if (isset($children->p->pPr->defRPr)) { - $font = $this->parseFont($children->p); - if ($font !== null) { - $axisText->setFont($font); - $addAxisText = true; - } - } - if (isset($children->p->pPr->defRPr->effectLst)) { - $this->readEffects($children->p->pPr->defRPr, $axisText, false); - $addAxisText = true; - } - if ($addAxisText) { - $whichAxis->setAxisText($axisText); - } } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php index 210c322f9..dac76230c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php @@ -22,18 +22,6 @@ class DataValidations public function load(): void { - foreach ($this->worksheetXml->dataValidations->dataValidation as $dataValidation) { - // Uppercase coordinate - $range = strtoupper((string) $dataValidation['sqref']); - $rangeSet = explode(' ', $range); - foreach ($rangeSet as $range) { - if (preg_match('/^[A-Z]{1,3}\\d{1,7}/', $range, $matches) === 1) { - // Ensure left/top row of range exists, thereby - // adjusting high row/column. - $this->worksheet->getCell($matches[0]); - } - } - } foreach ($this->worksheetXml->dataValidations->dataValidation as $dataValidation) { // Uppercase coordinate $range = strtoupper((string) $dataValidation['sqref']); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php index 0d4701afa..72addffd5 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php @@ -73,9 +73,6 @@ class Properties if (isset($xmlCore->Manager)) { $this->docProps->setManager((string) $xmlCore->Manager); } - if (isset($xmlCore->HyperlinkBase)) { - $this->docProps->setHyperlinkBase((string) $xmlCore->HyperlinkBase); - } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SharedFormula.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SharedFormula.php deleted file mode 100644 index fb7a39320..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SharedFormula.php +++ /dev/null @@ -1,26 +0,0 @@ -master = $master; - $this->formula = $formula; - } - - public function master(): string - { - return $this->master; - } - - public function formula(): string - { - return $this->formula; - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php index 5a360fda1..705b319e7 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php @@ -136,10 +136,6 @@ class Styles extends BaseParserClass } } } - if (isset($fontStyleXml->scheme)) { - $attr = $this->getStyleAttributes($fontStyleXml->scheme); - $fontStyle->setScheme((string) $attr['val']); - } } private function readNumberFormat(NumberFormat $numfmtStyle, SimpleXMLElement $numfmtStyleXml): void @@ -257,14 +253,10 @@ class Styles extends BaseParserClass public function readAlignmentStyle(Alignment $alignment, SimpleXMLElement $alignmentXml): void { - $horizontal = (string) $this->getAttribute($alignmentXml, 'horizontal'); - if ($horizontal !== '') { - $alignment->setHorizontal($horizontal); - } - $vertical = (string) $this->getAttribute($alignmentXml, 'vertical'); - if ($vertical !== '') { - $alignment->setVertical($vertical); - } + $horizontal = $this->getAttribute($alignmentXml, 'horizontal'); + $alignment->setHorizontal($horizontal); + $vertical = $this->getAttribute($alignmentXml, 'vertical'); + $alignment->setVertical((string) $vertical); $textRotation = (int) $this->getAttribute($alignmentXml, 'textRotation'); if ($textRotation > 90) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php index 6be26fc2c..9cce7003f 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php @@ -9,7 +9,6 @@ use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Cell\DataType; use PhpOffice\PhpSpreadsheet\DefinedName; use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner; -use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces; use PhpOffice\PhpSpreadsheet\Reader\Xml\PageSettings; use PhpOffice\PhpSpreadsheet\Reader\Xml\Properties; use PhpOffice\PhpSpreadsheet\Reader\Xml\Style; @@ -27,8 +26,6 @@ use SimpleXMLElement; */ class Xml extends BaseReader { - public const NAMESPACES_SS = 'urn:schemas-microsoft-com:office:spreadsheet'; - /** * Formats. * @@ -149,9 +146,11 @@ class Xml extends BaseReader throw new Exception("Problem reading {$filename}"); } - $xml_ss = $xml->children(self::NAMESPACES_SS); + $namespaces = $xml->getNamespaces(true); + + $xml_ss = $xml->children($namespaces['ss']); foreach ($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = self::getAttributes($worksheet, self::NAMESPACES_SS); + $worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']); $worksheetNames[] = (string) $worksheet_ss['Name']; } @@ -179,10 +178,12 @@ class Xml extends BaseReader throw new Exception("Problem reading {$filename}"); } + $namespaces = $xml->getNamespaces(true); + $worksheetID = 1; - $xml_ss = $xml->children(self::NAMESPACES_SS); + $xml_ss = $xml->children($namespaces['ss']); foreach ($xml_ss->Worksheet as $worksheet) { - $worksheet_ss = self::getAttributes($worksheet, self::NAMESPACES_SS); + $worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']); $tmpInfo = []; $tmpInfo['worksheetName'] = ''; @@ -230,19 +231,6 @@ class Xml extends BaseReader return $worksheetInfo; } - /** - * Loads Spreadsheet from string. - */ - public function loadSpreadsheetFromString(string $contents): Spreadsheet - { - // Create new Spreadsheet - $spreadsheet = new Spreadsheet(); - $spreadsheet->removeSheetByIndex(0); - - // Load into this instance - return $this->loadIntoExisting($contents, $spreadsheet, true); - } - /** * Loads Spreadsheet from file. */ @@ -257,19 +245,17 @@ class Xml extends BaseReader } /** - * Loads from file or contents into Spreadsheet instance. + * Loads from file into Spreadsheet instance. * - * @param string $filename file name if useContents is false else file contents + * @param string $filename + * + * @return Spreadsheet */ - public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet, bool $useContents = false): Spreadsheet + public function loadIntoExisting($filename, Spreadsheet $spreadsheet) { - if ($useContents) { - $this->fileContents = $filename; - } else { - File::assertFile($filename); - if (!$this->canRead($filename)) { - throw new Exception($filename . ' is an Invalid Spreadsheet file.'); - } + File::assertFile($filename); + if (!$this->canRead($filename)) { + throw new Exception($filename . ' is an Invalid Spreadsheet file.'); } $xml = $this->trySimpleXMLLoadString($filename); @@ -282,17 +268,14 @@ class Xml extends BaseReader (new Properties($spreadsheet))->readProperties($xml, $namespaces); $this->styles = (new Style())->parseStyles($xml, $namespaces); - if (isset($this->styles['Default'])) { - $spreadsheet->getCellXfCollection()[0]->applyFromArray($this->styles['Default']); - } $worksheetID = 0; - $xml_ss = $xml->children(self::NAMESPACES_SS); + $xml_ss = $xml->children($namespaces['ss']); /** @var null|SimpleXMLElement $worksheetx */ foreach ($xml_ss->Worksheet as $worksheetx) { $worksheet = $worksheetx ?? new SimpleXMLElement(''); - $worksheet_ss = self::getAttributes($worksheet, self::NAMESPACES_SS); + $worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']); if ( isset($this->loadSheetsOnly, $worksheet_ss['Name']) && @@ -312,15 +295,11 @@ class Xml extends BaseReader // the worksheet name in line with the formula, not the reverse $spreadsheet->getActiveSheet()->setTitle($worksheetName, false, false); } - if (isset($worksheet_ss['Protected'])) { - $protection = (string) $worksheet_ss['Protected'] === '1'; - $spreadsheet->getActiveSheet()->getProtection()->setSheet($protection); - } // locally scoped defined names if (isset($worksheet->Names[0])) { foreach ($worksheet->Names[0] as $definedName) { - $definedName_ss = self::getAttributes($definedName, self::NAMESPACES_SS); + $definedName_ss = self::getAttributes($definedName, $namespaces['ss']); $name = (string) $definedName_ss['Name']; $definedValue = (string) $definedName_ss['RefersTo']; $convertedValue = AddressHelper::convertFormulaToA1($definedValue); @@ -334,35 +313,15 @@ class Xml extends BaseReader $columnID = 'A'; if (isset($worksheet->Table->Column)) { foreach ($worksheet->Table->Column as $columnData) { - $columnData_ss = self::getAttributes($columnData, self::NAMESPACES_SS); - $colspan = 0; - if (isset($columnData_ss['Span'])) { - $spanAttr = (string) $columnData_ss['Span']; - if (is_numeric($spanAttr)) { - $colspan = max(0, (int) $spanAttr); - } - } + $columnData_ss = self::getAttributes($columnData, $namespaces['ss']); if (isset($columnData_ss['Index'])) { $columnID = Coordinate::stringFromColumnIndex((int) $columnData_ss['Index']); } - $columnWidth = null; if (isset($columnData_ss['Width'])) { $columnWidth = $columnData_ss['Width']; + $spreadsheet->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); } - $columnVisible = null; - if (isset($columnData_ss['Hidden'])) { - $columnVisible = ((string) $columnData_ss['Hidden']) !== '1'; - } - while ($colspan >= 0) { - if (isset($columnWidth)) { - $spreadsheet->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); - } - if (isset($columnVisible)) { - $spreadsheet->getActiveSheet()->getColumnDimension($columnID)->setVisible($columnVisible); - } - ++$columnID; - --$colspan; - } + ++$columnID; } } @@ -371,18 +330,14 @@ class Xml extends BaseReader $additionalMergedCells = 0; foreach ($worksheet->Table->Row as $rowData) { $rowHasData = false; - $row_ss = self::getAttributes($rowData, self::NAMESPACES_SS); + $row_ss = self::getAttributes($rowData, $namespaces['ss']); if (isset($row_ss['Index'])) { $rowID = (int) $row_ss['Index']; } - if (isset($row_ss['Hidden'])) { - $rowVisible = ((string) $row_ss['Hidden']) !== '1'; - $spreadsheet->getActiveSheet()->getRowDimension($rowID)->setVisible($rowVisible); - } $columnID = 'A'; foreach ($rowData->Cell as $cell) { - $cell_ss = self::getAttributes($cell, self::NAMESPACES_SS); + $cell_ss = self::getAttributes($cell, $namespaces['ss']); if (isset($cell_ss['Index'])) { $columnID = Coordinate::stringFromColumnIndex((int) $cell_ss['Index']); } @@ -424,7 +379,7 @@ class Xml extends BaseReader $cellData = $cell->Data; $cellValue = (string) $cellData; $type = DataType::TYPE_NULL; - $cellData_ss = self::getAttributes($cellData, self::NAMESPACES_SS); + $cellData_ss = self::getAttributes($cellData, $namespaces['ss']); if (isset($cellData_ss['Type'])) { $cellDataType = $cellData_ss['Type']; switch ($cellDataType) { @@ -482,7 +437,7 @@ class Xml extends BaseReader } if (isset($cell->Comment)) { - $this->parseCellComment($cell->Comment, $spreadsheet, $columnID, $rowID); + $this->parseCellComment($cell->Comment, $namespaces, $spreadsheet, $columnID, $rowID); } if (isset($cell_ss['StyleID'])) { @@ -511,57 +466,11 @@ class Xml extends BaseReader ++$rowID; } - } - $dataValidations = new Xml\DataValidations(); - $dataValidations->loadDataValidations($worksheet, $spreadsheet); - $xmlX = $worksheet->children(Namespaces::URN_EXCEL); - if (isset($xmlX->WorksheetOptions)) { - if (isset($xmlX->WorksheetOptions->FreezePanes)) { - $freezeRow = $freezeColumn = 1; - if (isset($xmlX->WorksheetOptions->SplitHorizontal)) { - $freezeRow = (int) $xmlX->WorksheetOptions->SplitHorizontal + 1; - } - if (isset($xmlX->WorksheetOptions->SplitVertical)) { - $freezeColumn = (int) $xmlX->WorksheetOptions->SplitVertical + 1; - } - $spreadsheet->getActiveSheet()->freezePane(Coordinate::stringFromColumnIndex($freezeColumn) . (string) $freezeRow); - } - (new PageSettings($xmlX))->loadPageSettings($spreadsheet); - if (isset($xmlX->WorksheetOptions->TopRowVisible, $xmlX->WorksheetOptions->LeftColumnVisible)) { - $leftTopRow = (string) $xmlX->WorksheetOptions->TopRowVisible; - $leftTopColumn = (string) $xmlX->WorksheetOptions->LeftColumnVisible; - if (is_numeric($leftTopRow) && is_numeric($leftTopColumn)) { - $leftTopCoordinate = Coordinate::stringFromColumnIndex((int) $leftTopColumn + 1) . (string) ($leftTopRow + 1); - $spreadsheet->getActiveSheet()->setTopLeftCell($leftTopCoordinate); - } - } - $rangeCalculated = false; - if (isset($xmlX->WorksheetOptions->Panes->Pane->RangeSelection)) { - if (1 === preg_match('/^R(\d+)C(\d+):R(\d+)C(\d+)$/', (string) $xmlX->WorksheetOptions->Panes->Pane->RangeSelection, $selectionMatches)) { - $selectedCell = Coordinate::stringFromColumnIndex((int) $selectionMatches[2]) - . $selectionMatches[1] - . ':' - . Coordinate::stringFromColumnIndex((int) $selectionMatches[4]) - . $selectionMatches[3]; - $spreadsheet->getActiveSheet()->setSelectedCells($selectedCell); - $rangeCalculated = true; - } - } - if (!$rangeCalculated) { - if (isset($xmlX->WorksheetOptions->Panes->Pane->ActiveRow)) { - $activeRow = (string) $xmlX->WorksheetOptions->Panes->Pane->ActiveRow; - } else { - $activeRow = 0; - } - if (isset($xmlX->WorksheetOptions->Panes->Pane->ActiveCol)) { - $activeColumn = (string) $xmlX->WorksheetOptions->Panes->Pane->ActiveCol; - } else { - $activeColumn = 0; - } - if (is_numeric($activeRow) && is_numeric($activeColumn)) { - $selectedCell = Coordinate::stringFromColumnIndex((int) $activeColumn + 1) . (string) ($activeRow + 1); - $spreadsheet->getActiveSheet()->setSelectedCells($selectedCell); + if (isset($namespaces['x'])) { + $xmlX = $worksheet->children($namespaces['x']); + if (isset($xmlX->WorksheetOptions)) { + (new PageSettings($xmlX, $namespaces))->loadPageSettings($spreadsheet); } } } @@ -569,14 +478,10 @@ class Xml extends BaseReader } // Globally scoped defined names - $activeSheetIndex = 0; - if (isset($xml->ExcelWorkbook->ActiveSheet)) { - $activeSheetIndex = (int) (string) $xml->ExcelWorkbook->ActiveSheet; - } - $activeWorksheet = $spreadsheet->setActiveSheetIndex($activeSheetIndex); + $activeWorksheet = $spreadsheet->setActiveSheetIndex(0); if (isset($xml->Names[0])) { foreach ($xml->Names[0] as $definedName) { - $definedName_ss = self::getAttributes($definedName, self::NAMESPACES_SS); + $definedName_ss = self::getAttributes($definedName, $namespaces['ss']); $name = (string) $definedName_ss['Name']; $definedValue = (string) $definedName_ss['RefersTo']; $convertedValue = AddressHelper::convertFormulaToA1($definedValue); @@ -593,11 +498,12 @@ class Xml extends BaseReader protected function parseCellComment( SimpleXMLElement $comment, + array $namespaces, Spreadsheet $spreadsheet, string $columnID, int $rowID ): void { - $commentAttributes = $comment->attributes(self::NAMESPACES_SS); + $commentAttributes = $comment->attributes($namespaces['ss']); $author = 'unknown'; if (isset($commentAttributes->Author)) { $author = (string) $commentAttributes->Author; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/DataValidations.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/DataValidations.php deleted file mode 100644 index 31748cb9c..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/DataValidations.php +++ /dev/null @@ -1,177 +0,0 @@ - DataValidation::OPERATOR_BETWEEN, - 'equal' => DataValidation::OPERATOR_EQUAL, - 'greater' => DataValidation::OPERATOR_GREATERTHAN, - 'greaterorequal' => DataValidation::OPERATOR_GREATERTHANOREQUAL, - 'less' => DataValidation::OPERATOR_LESSTHAN, - 'lessorequal' => DataValidation::OPERATOR_LESSTHANOREQUAL, - 'notbetween' => DataValidation::OPERATOR_NOTBETWEEN, - 'notequal' => DataValidation::OPERATOR_NOTEQUAL, - ]; - - private const TYPE_MAPPINGS = [ - 'textlength' => DataValidation::TYPE_TEXTLENGTH, - ]; - - private int $thisRow = 0; - - private int $thisColumn = 0; - - private function replaceR1C1(array $matches): string - { - return AddressHelper::convertToA1($matches[0], $this->thisRow, $this->thisColumn, false); - } - - public function loadDataValidations(SimpleXMLElement $worksheet, Spreadsheet $spreadsheet): void - { - $xmlX = $worksheet->children(Namespaces::URN_EXCEL); - $sheet = $spreadsheet->getActiveSheet(); - /** @var callable */ - $pregCallback = [$this, 'replaceR1C1']; - foreach ($xmlX->DataValidation as $dataValidation) { - $cells = []; - $validation = new DataValidation(); - - // set defaults - $validation->setShowDropDown(true); - $validation->setShowInputMessage(true); - $validation->setShowErrorMessage(true); - $validation->setShowDropDown(true); - $this->thisRow = 1; - $this->thisColumn = 1; - - foreach ($dataValidation as $tagName => $tagValue) { - $tagValue = (string) $tagValue; - $tagValueLower = strtolower($tagValue); - switch ($tagName) { - case 'Range': - foreach (explode(',', $tagValue) as $range) { - $cell = ''; - if (preg_match('/^R(\d+)C(\d+):R(\d+)C(\d+)$/', (string) $range, $selectionMatches) === 1) { - // range - $firstCell = Coordinate::stringFromColumnIndex((int) $selectionMatches[2]) - . $selectionMatches[1]; - $cell = $firstCell - . ':' - . Coordinate::stringFromColumnIndex((int) $selectionMatches[4]) - . $selectionMatches[3]; - $this->thisRow = (int) $selectionMatches[1]; - $this->thisColumn = (int) $selectionMatches[2]; - $sheet->getCell($firstCell); - } elseif (preg_match('/^R(\d+)C(\d+)$/', (string) $range, $selectionMatches) === 1) { - // cell - $cell = Coordinate::stringFromColumnIndex((int) $selectionMatches[2]) - . $selectionMatches[1]; - $sheet->getCell($cell); - $this->thisRow = (int) $selectionMatches[1]; - $this->thisColumn = (int) $selectionMatches[2]; - } elseif (preg_match('/^C(\d+)$/', (string) $range, $selectionMatches) === 1) { - // column - $firstCell = Coordinate::stringFromColumnIndex((int) $selectionMatches[1]) - . '1'; - $cell = $firstCell - . ':' - . Coordinate::stringFromColumnIndex((int) $selectionMatches[1]) - . ((string) AddressRange::MAX_ROW); - $this->thisColumn = (int) $selectionMatches[1]; - $sheet->getCell($firstCell); - } elseif (preg_match('/^R(\d+)$/', (string) $range, $selectionMatches)) { - // row - $firstCell = 'A' - . $selectionMatches[1]; - $cell = $firstCell - . ':' - . AddressRange::MAX_COLUMN - . $selectionMatches[1]; - $this->thisRow = (int) $selectionMatches[1]; - $sheet->getCell($firstCell); - } - - $validation->setSqref($cell); - $stRange = $sheet->shrinkRangeToFit($cell); - $cells = array_merge($cells, Coordinate::extractAllCellReferencesInRange($stRange)); - } - - break; - case 'Type': - $validation->setType(self::TYPE_MAPPINGS[$tagValueLower] ?? $tagValueLower); - - break; - case 'Qualifier': - $validation->setOperator(self::OPERATOR_MAPPINGS[$tagValueLower] ?? $tagValueLower); - - break; - case 'InputTitle': - $validation->setPromptTitle($tagValue); - - break; - case 'InputMessage': - $validation->setPrompt($tagValue); - - break; - case 'InputHide': - $validation->setShowInputMessage(false); - - break; - case 'ErrorStyle': - $validation->setErrorStyle($tagValueLower); - - break; - case 'ErrorTitle': - $validation->setErrorTitle($tagValue); - - break; - case 'ErrorMessage': - $validation->setError($tagValue); - - break; - case 'ErrorHide': - $validation->setShowErrorMessage(false); - - break; - case 'ComboHide': - $validation->setShowDropDown(false); - - break; - case 'UseBlank': - $validation->setAllowBlank(true); - - break; - case 'CellRangeList': - // FIXME missing FIXME - - break; - case 'Min': - case 'Value': - $tagValue = (string) preg_replace_callback(AddressHelper::R1C1_COORDINATE_REGEX, $pregCallback, $tagValue); - $validation->setFormula1($tagValue); - - break; - case 'Max': - $tagValue = (string) preg_replace_callback(AddressHelper::R1C1_COORDINATE_REGEX, $pregCallback, $tagValue); - $validation->setFormula2($tagValue); - - break; - } - } - - foreach ($cells as $cell) { - $sheet->getCell($cell)->setDataValidation(clone $validation); - } - } - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php index 137cabaf3..39535c3e7 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php @@ -2,7 +2,6 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xml; -use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup; use SimpleXMLElement; @@ -15,9 +14,9 @@ class PageSettings */ private $printSettings; - public function __construct(SimpleXMLElement $xmlX) + public function __construct(SimpleXMLElement $xmlX, array $namespaces) { - $printSettings = $this->pageSetup($xmlX, $this->getPrintDefaults()); + $printSettings = $this->pageSetup($xmlX, $namespaces, $this->getPrintDefaults()); $this->printSettings = $this->printSetup($xmlX, $printSettings); } @@ -57,13 +56,13 @@ class PageSettings ]; } - private function pageSetup(SimpleXMLElement $xmlX, stdClass $printDefaults): stdClass + private function pageSetup(SimpleXMLElement $xmlX, array $namespaces, stdClass $printDefaults): stdClass { if (isset($xmlX->WorksheetOptions->PageSetup)) { foreach ($xmlX->WorksheetOptions->PageSetup as $pageSetupData) { foreach ($pageSetupData as $pageSetupKey => $pageSetupValue) { /** @scrutinizer ignore-call */ - $pageSetupAttributes = $pageSetupValue->attributes(Namespaces::URN_EXCEL); + $pageSetupAttributes = $pageSetupValue->attributes($namespaces['x']); if ($pageSetupAttributes !== null) { switch ($pageSetupKey) { case 'Layout': diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php index e216c254d..f0346ed02 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php @@ -92,10 +92,6 @@ class Properties case 'Manager': $docProps->setManager($stringValue); - break; - case 'HyperlinkBase': - $docProps->setHyperlinkBase($stringValue); - break; case 'Keywords': $docProps->setKeywords($stringValue); @@ -114,10 +110,17 @@ class Properties ?SimpleXMLElement $propertyValue, SimpleXMLElement $propertyAttributes ): void { + $propertyType = DocumentProperties::PROPERTY_TYPE_UNKNOWN; + switch ((string) $propertyAttributes) { + case 'string': + $propertyType = DocumentProperties::PROPERTY_TYPE_STRING; + $propertyValue = trim((string) $propertyValue); + + break; case 'boolean': $propertyType = DocumentProperties::PROPERTY_TYPE_BOOLEAN; - $propertyValue = (bool) (string) $propertyValue; + $propertyValue = (bool) $propertyValue; break; case 'integer': @@ -131,15 +134,9 @@ class Properties break; case 'dateTime.tz': - case 'dateTime.iso8601tz': $propertyType = DocumentProperties::PROPERTY_TYPE_DATE; $propertyValue = trim((string) $propertyValue); - break; - default: - $propertyType = DocumentProperties::PROPERTY_TYPE_STRING; - $propertyValue = trim((string) $propertyValue); - break; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php index 698acf6ac..774fffe8b 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php @@ -2,7 +2,6 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xml; -use PhpOffice\PhpSpreadsheet\Style\Protection; use SimpleXMLElement; class Style @@ -31,7 +30,7 @@ class Style $styleID = (string) $style_ss['ID']; $this->styles[$styleID] = $this->styles['Default'] ?? []; - $alignment = $border = $font = $fill = $numberFormat = $protection = []; + $alignment = $border = $font = $fill = $numberFormat = []; foreach ($style as $styleType => $styleDatax) { $styleData = self::getSxml($styleDatax); @@ -65,31 +64,11 @@ class Style $numberFormat = $numberFormatStyleParser->parseStyle($styleAttributes); } - break; - case 'Protection': - $locked = $hidden = null; - $styleAttributesP = $styleData->attributes($namespaces['x']); - if (isset($styleAttributes['Protected'])) { - $locked = ((bool) (string) $styleAttributes['Protected']) ? Protection::PROTECTION_PROTECTED : Protection::PROTECTION_UNPROTECTED; - } - if (isset($styleAttributesP['HideFormula'])) { - $hidden = ((bool) (string) $styleAttributesP['HideFormula']) ? Protection::PROTECTION_PROTECTED : Protection::PROTECTION_UNPROTECTED; - } - if ($locked !== null || $hidden !== null) { - $protection['protection'] = []; - if ($locked !== null) { - $protection['protection']['locked'] = $locked; - } - if ($hidden !== null) { - $protection['protection']['hidden'] = $hidden; - } - } - break; } } - $this->styles[$styleID] = array_merge($alignment, $border, $font, $fill, $numberFormat, $protection); + $this->styles[$styleID] = array_merge($alignment, $border, $font, $fill, $numberFormat); } return $this->styles; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php index 5f824889a..16ab44d80 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php @@ -56,11 +56,11 @@ class Font extends StyleBase break; case 'Bold': - $style['font']['bold'] = $styleAttributeValue === '1'; + $style['font']['bold'] = true; break; case 'Italic': - $style['font']['italic'] = $styleAttributeValue === '1'; + $style['font']['italic'] = true; break; case 'Underline': diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php index 90eee534d..b4d4d52af 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php @@ -75,11 +75,14 @@ class ReferenceHelper * * @return int */ - public static function columnReverseSort(string $a, string $b) + public static function columnReverseSort($a, $b) { return -strcasecmp(strlen($a) . $a, strlen($b) . $b); } + /** @var int */ + private static $scrutinizer0 = 0; + /** * Compare two cell addresses * Intended for use as a Callback function for sorting cell addresses by column and row. @@ -89,16 +92,16 @@ class ReferenceHelper * * @return int */ - public static function cellSort(string $a, string $b) + public static function cellSort($a, $b) { - /** @scrutinizer be-damned */ + $ac = $bc = ''; + $ar = self::$scrutinizer0; + $br = 0; sscanf($a, '%[A-Z]%d', $ac, $ar); - /** @var int $ar */ - /** @var string $ac */ - /** @scrutinizer be-damned */ sscanf($b, '%[A-Z]%d', $bc, $br); - /** @var int $br */ - /** @var string $bc */ + + $ac = (string) $ac; + $bc = (string) $bc; if ($ar === $br) { return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); } @@ -115,16 +118,16 @@ class ReferenceHelper * * @return int */ - public static function cellReverseSort(string $a, string $b) + public static function cellReverseSort($a, $b) { - /** @scrutinizer be-damned */ + $ac = $bc = ''; + $ar = self::$scrutinizer0; + $br = 0; sscanf($a, '%[A-Z]%d', $ac, $ar); - /** @var int $ar */ - /** @var string $ac */ - /** @scrutinizer be-damned */ sscanf($b, '%[A-Z]%d', $bc, $br); - /** @var int $br */ - /** @var string $bc */ + + $ac = (string) $ac; + $bc = (string) $bc; if ($ar === $br) { return -strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); } @@ -139,7 +142,7 @@ class ReferenceHelper * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustPageBreaks(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void + protected function adjustPageBreaks(Worksheet $worksheet, $numberOfColumns, $numberOfRows): void { $aBreaks = $worksheet->getBreaks(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -168,7 +171,7 @@ class ReferenceHelper * * @param Worksheet $worksheet The worksheet that we're editing */ - protected function adjustComments(Worksheet $worksheet): void + protected function adjustComments($worksheet): void { $aComments = $worksheet->getComments(); $aNewComments = []; // the new array of all comments @@ -192,7 +195,7 @@ class ReferenceHelper * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustHyperlinks(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void + protected function adjustHyperlinks($worksheet, $numberOfColumns, $numberOfRows): void { $aHyperlinkCollection = $worksheet->getHyperlinkCollection(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -217,7 +220,7 @@ class ReferenceHelper * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustConditionalFormatting(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void + protected function adjustConditionalFormatting($worksheet, $numberOfColumns, $numberOfRows): void { $aStyles = $worksheet->getConditionalStylesCollection(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -256,7 +259,7 @@ class ReferenceHelper * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustDataValidations(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void + protected function adjustDataValidations(Worksheet $worksheet, $numberOfColumns, $numberOfRows): void { $aDataValidationCollection = $worksheet->getDataValidationCollection(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -296,7 +299,7 @@ class ReferenceHelper * @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion) * @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion) */ - protected function adjustProtectedCells(Worksheet $worksheet, int $numberOfColumns, int $numberOfRows): void + protected function adjustProtectedCells(Worksheet $worksheet, $numberOfColumns, $numberOfRows): void { $aProtectedCells = $worksheet->getProtectedCells(); ($numberOfColumns > 0 || $numberOfRows > 0) @@ -409,7 +412,7 @@ class ReferenceHelper $cellCollection = $worksheet->getCellCollection(); $missingCoordinates = array_filter( array_map(function ($row) use ($highestColumn) { - return "{$highestColumn}{$row}"; + return $highestColumn . $row; }, range(1, $highestRow)), function ($coordinate) use ($cellCollection) { return $cellCollection->has($coordinate) === false; @@ -450,9 +453,9 @@ class ReferenceHelper if ($cell->getDataType() === DataType::TYPE_FORMULA) { // Formula should be adjusted $worksheet->getCell($newCoordinate) - ->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true)); + ->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle())); } else { - // Cell value should not be adjusted + // Formula should not be adjusted $worksheet->getCell($newCoordinate)->setValueExplicit($cell->getValue(), $cell->getDataType()); } @@ -460,10 +463,10 @@ class ReferenceHelper $worksheet->getCellCollection()->delete($coordinate); } else { /* We don't need to update styles for rows/columns before our insertion position, - but we do still need to adjust any formulae in those cells */ + but we do still need to adjust any formulae in those cells */ if ($cell->getDataType() === DataType::TYPE_FORMULA) { // Formula should be adjusted - $cell->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true)); + $cell->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle())); } } } @@ -606,7 +609,7 @@ class ReferenceHelper // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more $column = 100000; $row = 10000000 + (int) trim($match[3], '$'); - $cellIndex = "{$column}{$row}"; + $cellIndex = $column . $row; $newCellTokens[$cellIndex] = preg_quote($toString, '/'); $cellTokens[$cellIndex] = '/(?getValue(); $asFormula = ($cellAddress[0] === '='); if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) { - /** - * If we delete the entire range that is referenced by a Named Range, MS Excel sets the value to #REF! - * PhpSpreadsheet still only does a basic adjustment, so the Named Range will still reference Cells. - * Note that this applies only when deleting columns/rows; subsequent insertion won't fix the #REF! - * TODO Can we work out a method to identify Named Ranges that cease to be valid, so that we can replace - * them with a #REF! - */ if ($asFormula === true) { - $formula = $this->updateFormulaReferences($cellAddress, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true); + $formula = $this->updateFormulaReferences($cellAddress, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()); $definedName->setValue($formula); } else { - $definedName->setValue($this->updateCellReference(ltrim($cellAddress, '='), true)); + $definedName->setValue($this->updateCellReference(ltrim($cellAddress, '='))); } } } @@ -933,15 +929,8 @@ class ReferenceHelper private function updateNamedFormula(DefinedName $definedName, Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): void { if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) { - /** - * If we delete the entire range that is referenced by a Named Formula, MS Excel sets the value to #REF! - * PhpSpreadsheet still only does a basic adjustment, so the Named Formula will still reference Cells. - * Note that this applies only when deleting columns/rows; subsequent insertion won't fix the #REF! - * TODO Can we work out a method to identify Named Ranges that cease to be valid, so that we can replace - * them with a #REF! - */ $formula = $definedName->getValue(); - $formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true); + $formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()); $definedName->setValue($formula); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php index ee693a2b3..23733436b 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php @@ -47,7 +47,7 @@ class TextElement implements ITextElement } /** - * Get font. For this class, the return value is always null. + * Get font. * * @return null|\PhpOffice\PhpSpreadsheet\Style\Font */ diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php index d8007fd00..0baf44637 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php @@ -155,7 +155,7 @@ class Settings /** * Sets the implementation of cache that should be used for cell collection. */ - public static function setCache(?CacheInterface $cache): void + public static function setCache(CacheInterface $cache): void { self::$cache = $cache; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php index 4f1967311..26dde93f3 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php @@ -184,7 +184,7 @@ class Date throw new Exception("Invalid string $value supplied for datatype Date"); } - if (preg_match('/^\\s*\\d?\\d:\\d\\d(:\\d\\d([.]\\d+)?)?\\s*(am|pm)?\\s*$/i', $value) == 1) { + if (preg_match('/^\\d\\d:\\d\\d:\\d\\d/', $value) == 1) { $newValue = fmod($newValue, 1.0); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php index 737a6eb59..f2fe8caa8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php @@ -156,11 +156,7 @@ class File if ($zipMember !== '') { $zipfile = "zip://$filename#$zipMember"; if (!self::fileExists($zipfile)) { - // Has the file been saved with Windoze directory separators rather than unix? - $zipfile = "zip://$filename#" . str_replace('/', '\\', $zipMember); - if (!self::fileExists($zipfile)) { - throw new ReaderException("Could not find zip member $zipfile"); - } + throw new ReaderException("Could not find zip member $zipfile"); } } } @@ -184,14 +180,6 @@ class File return self::validateZipFirst4($filename); } - $zipfile = "zip://$filename#$zipMember"; - if (self::fileExists($zipfile)) { - return true; - } - - // Has the file been saved with Windoze directory separators rather than unix? - $zipfile = "zip://$filename#" . str_replace('/', '\\', $zipMember); - - return self::fileExists($zipfile); + return self::fileExists("zip://$filename#$zipMember"); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php index 90c1992a3..aa3512ae3 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php @@ -380,15 +380,15 @@ class Font $approximate = self::$autoSizeMethod === self::AUTOSIZE_METHOD_APPROX; $columnWidth = 0; if (!$approximate) { - try { - $columnWidthAdjust = ceil( - self::getTextWidthPixelsExact( - str_repeat('n', 1 * (($filterAdjustment ? 3 : 1) + ($indentAdjustment * 2))), - $font, - 0 - ) * 1.07 - ); + $columnWidthAdjust = ceil( + self::getTextWidthPixelsExact( + str_repeat('n', 1 * (($filterAdjustment ? 3 : 1) + ($indentAdjustment * 2))), + $font, + 0 + ) * 1.07 + ); + try { // Width of text in pixels excl. padding // and addition because Excel adds some padding, just use approx width of 'n' glyph $columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation) + $columnWidthAdjust; @@ -453,26 +453,29 @@ class Font $fontName = $font->getName(); $fontSize = $font->getSize(); - // Calculate column width in pixels. - // We assume fixed glyph width, but count double for "fullwidth" characters. - // Result varies with font name and size. + // Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size. switch ($fontName) { + case 'Calibri': + // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. + $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size + + break; case 'Arial': // value 8 was set because of experience in different exports at Arial 10 font. - $columnWidth = (int) (8 * StringHelper::countCharactersDbcs($columnText)); + $columnWidth = (int) (8 * StringHelper::countCharacters($columnText)); $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size break; case 'Verdana': // value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font. - $columnWidth = (int) (8 * StringHelper::countCharactersDbcs($columnText)); + $columnWidth = (int) (8 * StringHelper::countCharacters($columnText)); $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size break; default: // just assume Calibri - // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. - $columnWidth = (int) (8.26 * StringHelper::countCharactersDbcs($columnText)); + $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText)); $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size break; @@ -561,13 +564,10 @@ class Font if (mb_strlen(self::$trueTypeFontPath) > 1 && mb_substr(self::$trueTypeFontPath, -1) !== '/' && mb_substr(self::$trueTypeFontPath, -1) !== '\\') { $separator = DIRECTORY_SEPARATOR; } - $fontFileAbsolute = preg_match('~^([A-Za-z]:)?[/\\\\]~', $fontFile) === 1; - if (!$fontFileAbsolute) { - $fontFile = self::$trueTypeFontPath . $separator . $fontFile; - } + $fontFile = self::$trueTypeFontPath . $separator . $fontFile; // Check if file actually exists - if ($checkPath && !file_exists($fontFile) && !$fontFileAbsolute) { + if ($checkPath && !file_exists($fontFile)) { $alternateName = $name; if ($index !== 'x' && $fontArray[$name][$index] !== $fontArray[$name]['x']) { // Bold but no italic: diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php index 5d5babc3f..c61ee2594 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php @@ -6,9 +6,6 @@ use PhpOffice\PhpSpreadsheet\Shared\OLE; class ChainedBlockStream { - /** @var mixed */ - public $context; - /** * The OLE container of the file that is being read. * @@ -163,7 +160,7 @@ class ChainedBlockStream $this->pos = $offset; } elseif ($whence == SEEK_CUR && -$offset <= $this->pos) { $this->pos += $offset; - // @phpstan-ignore-next-line + // @phpstan-ignore-next-line } elseif ($whence == SEEK_END && -$offset <= count(/** @scrutinizer ignore-type */ $this->data)) { $this->pos = strlen($this->data) + $offset; } else { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php index fcc963953..3d952a9c8 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php @@ -134,7 +134,7 @@ class OLERead $bbdBlocks = $this->numBigBlockDepotBlocks; - if ($this->numExtensionBlocks !== 0) { + if ($this->numExtensionBlocks != 0) { $bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS) / 4; } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php index c6c198e20..30bd8c5fd 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php @@ -451,18 +451,6 @@ class StringHelper return mb_strlen($textValue, $encoding); } - /** - * Get character count using mb_strwidth rather than mb_strlen. - * - * @param string $encoding Encoding - * - * @return int Character count - */ - public static function countCharactersDbcs(string $textValue, string $encoding = 'UTF-8'): int - { - return mb_strwidth($textValue, $encoding); - } - /** * Get a substring of a UTF-8 encoded string. * diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php index 117848c77..b94609af7 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php @@ -105,6 +105,7 @@ class Trend $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit'; //* @phpstan-ignore-next-line $bestFit[$trendMethod] = new $className($yValues, $xValues, $const); + //* @phpstan-ignore-next-line $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit(); } if ($trendType != self::TREND_BEST_FIT_NO_POLY) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php index 110908550..f0744cd27 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php @@ -203,14 +203,6 @@ class Spreadsheet implements JsonSerializable */ private $tabRatio = 600; - /** @var Theme */ - private $theme; - - public function getTheme(): Theme - { - return $this->theme; - } - /** * The workbook has macros ? * @@ -484,7 +476,6 @@ class Spreadsheet implements JsonSerializable { $this->uniqueID = uniqid('', true); $this->calculationEngine = new Calculation($this); - $this->theme = new Theme(); // Initialise worksheet collection and add one worksheet $this->workSheetCollection = []; @@ -1663,26 +1654,4 @@ class Spreadsheet implements JsonSerializable { throw new Exception('Spreadsheet objects cannot be json encoded'); } - - public function resetThemeFonts(): void - { - $majorFontLatin = $this->theme->getMajorFontLatin(); - $minorFontLatin = $this->theme->getMinorFontLatin(); - foreach ($this->cellXfCollection as $cellStyleXf) { - $scheme = $cellStyleXf->getFont()->getScheme(); - if ($scheme === 'major') { - $cellStyleXf->getFont()->setName($majorFontLatin)->setScheme($scheme); - } elseif ($scheme === 'minor') { - $cellStyleXf->getFont()->setName($minorFontLatin)->setScheme($scheme); - } - } - foreach ($this->cellStyleXfCollection as $cellStyleXf) { - $scheme = $cellStyleXf->getFont()->getScheme(); - if ($scheme === 'major') { - $cellStyleXf->getFont()->setName($majorFontLatin)->setScheme($scheme); - } elseif ($scheme === 'minor') { - $cellStyleXf->getFont()->setName($minorFontLatin)->setScheme($scheme); - } - } - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php index 282defc0c..3c002b270 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php @@ -362,8 +362,23 @@ class Color extends Supervisor $green = self::getGreen($hexColourValue, false); /** @var int $blue */ $blue = self::getBlue($hexColourValue, false); + if ($adjustPercentage > 0) { + $red += (255 - $red) * $adjustPercentage; + $green += (255 - $green) * $adjustPercentage; + $blue += (255 - $blue) * $adjustPercentage; + } else { + $red += $red * $adjustPercentage; + $green += $green * $adjustPercentage; + $blue += $blue * $adjustPercentage; + } - return (($rgba) ? 'FF' : '') . RgbTint::rgbAndTintToRgb($red, $green, $blue, $adjustPercentage); + $rgb = strtoupper( + str_pad(dechex((int) $red), 2, '0', 0) . + str_pad(dechex((int) $green), 2, '0', 0) . + str_pad(dechex((int) $blue), 2, '0', 0) + ); + + return (($rgba) ? 'FF' : '') . $rgb; } /** diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php index 36069b00c..de565d345 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php @@ -248,7 +248,7 @@ class Conditional implements IComparable /** * Set Conditions. * - * @param (bool|float|int|string)[]|bool|float|int|string $conditions Condition + * @param bool|float|int|string|(bool|float|int|string)[] $conditions Condition * * @return $this */ diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php index a8eeaa986..3d7bc1bce 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php @@ -107,9 +107,6 @@ class Font extends Supervisor */ public $colorIndex; - /** @var string */ - protected $scheme = ''; - /** * Create a new Font. * @@ -234,12 +231,6 @@ class Font extends Supervisor if (isset($styleArray['size'])) { $this->setSize($styleArray['size']); } - if (isset($styleArray['chartColor'])) { - $this->chartColor = $styleArray['chartColor']; - } - if (isset($styleArray['scheme'])) { - $this->setScheme($styleArray['scheme']); - } } return $this; @@ -287,11 +278,13 @@ class Font extends Supervisor } /** - * Set Name and turn off Scheme. + * Set Name. * * @param string $fontname + * + * @return $this */ - public function setName($fontname): self + public function setName($fontname) { if ($fontname == '') { $fontname = 'Calibri'; @@ -303,7 +296,7 @@ class Font extends Supervisor $this->name = $fontname; } - return $this->setScheme(''); + return $this; } public function setLatin(string $fontname): self @@ -641,13 +634,6 @@ class Font extends Supervisor return $this; } - public function setChartColorFromObject(?ChartColor $chartColor): self - { - $this->chartColor = $chartColor; - - return $this; - } - /** * Get Underline. * @@ -788,7 +774,6 @@ class Font extends Supervisor $this->underline . ($this->strikethrough ? 't' : 'f') . $this->color->getHashCode() . - $this->scheme . implode( '*', [ @@ -817,7 +802,6 @@ class Font extends Supervisor $this->exportArray2($exportedArray, 'italic', $this->getItalic()); $this->exportArray2($exportedArray, 'latin', $this->getLatin()); $this->exportArray2($exportedArray, 'name', $this->getName()); - $this->exportArray2($exportedArray, 'scheme', $this->getScheme()); $this->exportArray2($exportedArray, 'size', $this->getSize()); $this->exportArray2($exportedArray, 'strikethrough', $this->getStrikethrough()); $this->exportArray2($exportedArray, 'strikeType', $this->getStrikeType()); @@ -828,27 +812,4 @@ class Font extends Supervisor return $exportedArray; } - - public function getScheme(): string - { - if ($this->isSupervisor) { - return $this->getSharedComponent()->getScheme(); - } - - return $this->scheme; - } - - public function setScheme(string $scheme): self - { - if ($scheme === '' || $scheme === 'major' || $scheme === 'minor') { - if ($this->isSupervisor) { - $styleArray = $this->getStyleArray(['scheme' => $scheme]); - $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); - } else { - $this->scheme = $scheme; - } - } - - return $this; - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php index 41a17151d..de3666ae1 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php @@ -3,7 +3,6 @@ namespace PhpOffice\PhpSpreadsheet\Style\NumberFormat; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; -use PhpOffice\PhpSpreadsheet\Reader\Xls\Color\BIFF8; use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\Style\Color; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; @@ -68,19 +67,14 @@ class Formatter // 3 sections: [POSITIVE/TEXT] [NEGATIVE] [ZERO] // 4 sections: [POSITIVE] [NEGATIVE] [ZERO] [TEXT] $sectionCount = count($sections); - // Colour could be a named colour, or a numeric index entry in the colour-palette - $color_regex = '/\\[(' . implode('|', Color::NAMED_COLORS) . '|color\\s*(\\d+))\\]/mui'; + $color_regex = '/\\[(' . implode('|', Color::NAMED_COLORS) . ')\\]/mui'; $cond_regex = '/\\[(>|>=|<|<=|=|<>)([+-]?\\d+([.]\\d+)?)\\]/'; $colors = ['', '', '', '', '']; $conditionOperations = ['', '', '', '', '']; $conditionComparisonValues = [0, 0, 0, 0, 0]; for ($idx = 0; $idx < $sectionCount; ++$idx) { if (preg_match($color_regex, $sections[$idx], $matches)) { - if (isset($matches[2])) { - $colors[$idx] = '#' . BIFF8::lookup((int) $matches[2] + 7)['rgb']; - } else { - $colors[$idx] = $matches[0]; - } + $colors[$idx] = $matches[0]; $sections[$idx] = (string) preg_replace($color_regex, '', $sections[$idx]); } if (preg_match($cond_regex, $sections[$idx], $matches)) { @@ -176,11 +170,10 @@ class Formatter $format = (string) preg_replace('/_.?/ui', ' ', $format); // Let's begin inspecting the format and converting the value to a formatted string + // Check for date/time characters (not inside quotes) if ( - // Check for date/time characters (not inside quotes) - (preg_match('/(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy](?=(?:[^"]|"[^"]*")*$)/miu', $format)) - // A date/time with a decimal time shouldn't have a digit placeholder before the decimal point - && (preg_match('/[0\?#]\.(?![^\[]*\])/miu', $format) === 0) + (preg_match('/(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy](?=(?:[^"]|"[^"]*")*$)/miu', $format)) && + (preg_match('/0(?![^\[]*\])/miu', $format) === 0) ) { // datetime format $value = DateFormatter::format($value, $format); @@ -201,6 +194,8 @@ class Formatter $value = $writerInstance->$function($value, $colors); } - return str_replace(chr(0x00), '.', $value); + $value = str_replace(chr(0x00), '.', $value); + + return $value; } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php index c30028601..a138ab7f1 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php @@ -89,13 +89,13 @@ class Accounting extends Currency ( $this->currencySymbolPosition === self::LEADING_SYMBOL && $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING - ) ? "\u{a0}" : '', + ) ? ' ' : '', $this->thousandsSeparator ? '#,##' : null, $this->decimals > 0 ? '.' . str_repeat('0', $this->decimals) : null, ( $this->currencySymbolPosition === self::TRAILING_SYMBOL && $this->currencySymbolSpacing === self::SYMBOL_WITH_SPACING - ) ? "\u{a0}" : '', + ) ? ' ' : '', $this->currencySymbolPosition === self::TRAILING_SYMBOL ? $this->formatCurrencyCode() : null ); } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Date.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Date.php deleted file mode 100644 index 61ac117b7..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Date.php +++ /dev/null @@ -1,125 +0,0 @@ -separators = $this->padSeparatorArray( - is_array($separators) ? $separators : [$separators], - count($formatBlocks) - 1 - ); - $this->formatBlocks = array_map([$this, 'mapFormatBlocks'], $formatBlocks); - } - - private function mapFormatBlocks(string $value): string - { - // Any date masking codes are returned as lower case values - if (in_array(mb_strtolower($value), self::DATE_BLOCKS, true)) { - return mb_strtolower($value); - } - - // Wrap any string literals in quotes, so that they're clearly defined as string literals - return $this->wrapLiteral($value); - } - - public function format(): string - { - return implode('', array_map([$this, 'intersperse'], $this->formatBlocks, $this->separators)); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTime.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTime.php deleted file mode 100644 index 292c1efc9..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTime.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ - protected array $formatBlocks; - - /** - * @param null|string|string[] $separators - * If you want to use only a single format block, then pass a null as the separator argument - * @param DateTimeWizard|string ...$formatBlocks - */ - public function __construct($separators, ...$formatBlocks) - { - $this->separators = $this->padSeparatorArray( - is_array($separators) ? $separators : [$separators], - count($formatBlocks) - 1 - ); - $this->formatBlocks = array_map([$this, 'mapFormatBlocks'], $formatBlocks); - } - - /** - * @param DateTimeWizard|string $value - */ - private function mapFormatBlocks($value): string - { - // Any date masking codes are returned as lower case values - if (is_object($value)) { - // We can't explicitly test for Stringable until PHP >= 8.0 - return $value; - } - - // Wrap any string literals in quotes, so that they're clearly defined as string literals - return $this->wrapLiteral($value); - } - - public function format(): string - { - return implode('', array_map([$this, 'intersperse'], $this->formatBlocks, $this->separators)); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTimeWizard.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTimeWizard.php deleted file mode 100644 index b14a6190f..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTimeWizard.php +++ /dev/null @@ -1,44 +0,0 @@ -= "; - - protected function padSeparatorArray(array $separators, int $count): array - { - $lastSeparator = array_pop($separators); - - return $separators + array_fill(0, $count, $lastSeparator); - } - - protected function escapeSingleCharacter(string $value): string - { - if (strpos(self::NO_ESCAPING_NEEDED, $value) !== false) { - return $value; - } - - return "\\{$value}"; - } - - protected function wrapLiteral(string $value): string - { - if (mb_strlen($value, 'UTF-8') === 1) { - return $this->escapeSingleCharacter($value); - } - - // Wrap any other string literals in quotes, so that they're clearly defined as string literals - return '"' . str_replace('"', '""', $value) . '"'; - } - - protected function intersperse(string $formatBlock, ?string $separator): string - { - return "{$formatBlock}{$separator}"; - } - - public function __toString(): string - { - return $this->format(); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Duration.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Duration.php deleted file mode 100644 index b81f77acb..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Duration.php +++ /dev/null @@ -1,153 +0,0 @@ - self::DAYS_DURATION, - self::HOURS_DURATION => self::HOURS_SHORT, - self::MINUTES_DURATION => self::MINUTES_LONG, - self::SECONDS_DURATION => self::SECONDS_LONG, - ]; - - protected const DURATION_DEFAULTS = [ - self::HOURS_LONG => self::HOURS_DURATION, - self::HOURS_SHORT => self::HOURS_DURATION, - self::MINUTES_LONG => self::MINUTES_DURATION, - self::MINUTES_SHORT => self::MINUTES_DURATION, - self::SECONDS_LONG => self::SECONDS_DURATION, - self::SECONDS_SHORT => self::SECONDS_DURATION, - ]; - - public const SEPARATOR_COLON = ':'; - public const SEPARATOR_SPACE_NONBREAKING = "\u{a0}"; - public const SEPARATOR_SPACE = ' '; - - public const DURATION_DEFAULT = [ - self::HOURS_DURATION, - self::MINUTES_LONG, - self::SECONDS_LONG, - ]; - - /** - * @var string[] - */ - protected array $separators; - - /** - * @var string[] - */ - protected array $formatBlocks; - - protected bool $durationIsSet = false; - - /** - * @param null|string|string[] $separators - * If you want to use the same separator for all format blocks, then it can be passed as a string literal; - * if you wish to use different separators, then they should be passed as an array. - * If you want to use only a single format block, then pass a null as the separator argument - */ - public function __construct($separators = self::SEPARATOR_COLON, string ...$formatBlocks) - { - $separators ??= self::SEPARATOR_COLON; - $formatBlocks = (count($formatBlocks) === 0) ? self::DURATION_DEFAULT : $formatBlocks; - - $this->separators = $this->padSeparatorArray( - is_array($separators) ? $separators : [$separators], - count($formatBlocks) - 1 - ); - $this->formatBlocks = array_map([$this, 'mapFormatBlocks'], $formatBlocks); - - if ($this->durationIsSet === false) { - // We need at least one duration mask, so if none has been set we change the first mask element - // to a duration. - $this->formatBlocks[0] = self::DURATION_DEFAULTS[mb_strtolower($this->formatBlocks[0])]; - } - } - - private function mapFormatBlocks(string $value): string - { - // Any duration masking codes are returned as lower case values - if (in_array(mb_strtolower($value), self::DURATION_BLOCKS, true)) { - if (array_key_exists(mb_strtolower($value), self::DURATION_MASKS)) { - if ($this->durationIsSet) { - // We should only have a single duration mask, the first defined in the mask set, - // so convert any additional duration masks to standard time masks. - $value = self::DURATION_MASKS[mb_strtolower($value)]; - } - $this->durationIsSet = true; - } - - return mb_strtolower($value); - } - - // Wrap any string literals in quotes, so that they're clearly defined as string literals - return $this->wrapLiteral($value); - } - - public function format(): string - { - return implode('', array_map([$this, 'intersperse'], $this->formatBlocks, $this->separators)); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Time.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Time.php deleted file mode 100644 index 64b9104a6..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Time.php +++ /dev/null @@ -1,105 +0,0 @@ -separators = $this->padSeparatorArray( - is_array($separators) ? $separators : [$separators], - count($formatBlocks) - 1 - ); - $this->formatBlocks = array_map([$this, 'mapFormatBlocks'], $formatBlocks); - } - - private function mapFormatBlocks(string $value): string - { - // Any date masking codes are returned as lower case values - // except for AM/PM, which is set to uppercase - if (in_array(mb_strtolower($value), self::TIME_BLOCKS, true)) { - return mb_strtolower($value); - } elseif (mb_strtoupper($value) === self::MORNING_AFTERNOON) { - return mb_strtoupper($value); - } - - // Wrap any string literals in quotes, so that they're clearly defined as string literals - return $this->wrapLiteral($value); - } - - public function format(): string - { - return implode('', array_map([$this, 'intersperse'], $this->formatBlocks, $this->separators)); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/RgbTint.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/RgbTint.php deleted file mode 100644 index 582ae4839..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/RgbTint.php +++ /dev/null @@ -1,175 +0,0 @@ -= 0.0) ? $hue : (1.0 + $hue); - } - - /** - * Convert red/green/blue to HLSMAX-based hue/luminance/saturation. - * - * @return int[] - */ - private static function rgbToMsHls(int $red, int $green, int $blue): array - { - $red01 = $red / self::RGBMAX; - $green01 = $green / self::RGBMAX; - $blue01 = $blue / self::RGBMAX; - [$hue, $luminance, $saturation] = self::rgbToHls($red01, $green01, $blue01); - - return [ - (int) round($hue * self::HLSMAX), - (int) round($luminance * self::HLSMAX), - (int) round($saturation * self::HLSMAX), - ]; - } - - /** - * Converts HLSMAX based HLS values to rgb values in the range (0,1). - * - * @return float[] - */ - private static function msHlsToRgb(int $hue, int $lightness, int $saturation): array - { - return self::hlsToRgb($hue / self::HLSMAX, $lightness / self::HLSMAX, $saturation / self::HLSMAX); - } - - /** - * Tints HLSMAX based luminance. - * - * @see http://ciintelligence.blogspot.co.uk/2012/02/converting-excel-theme-color-and-tint.html - */ - private static function tintLuminance(float $tint, float $luminance): int - { - if ($tint < 0) { - return (int) round($luminance * (1.0 + $tint)); - } - - return (int) round($luminance * (1.0 - $tint) + (self::HLSMAX - self::HLSMAX * (1.0 - $tint))); - } - - /** - * Return result of tinting supplied rgb as 6 hex digits. - */ - public static function rgbAndTintToRgb(int $red, int $green, int $blue, float $tint): string - { - [$hue, $luminance, $saturation] = self::rgbToMsHls($red, $green, $blue); - [$red, $green, $blue] = self::msHlsToRgb($hue, self::tintLuminance($tint, $luminance), $saturation); - - return sprintf( - '%02X%02X%02X', - (int) round($red * self::RGBMAX), - (int) round($green * self::RGBMAX), - (int) round($blue * self::RGBMAX) - ); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php index 9309830bf..be70639eb 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php @@ -2,10 +2,7 @@ namespace PhpOffice\PhpSpreadsheet\Style; -use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; -use PhpOffice\PhpSpreadsheet\Exception; -use PhpOffice\PhpSpreadsheet\Shared\StringHelper; use PhpOffice\PhpSpreadsheet\Spreadsheet; class Style extends Supervisor @@ -125,7 +122,7 @@ class Style extends Supervisor public function getSharedComponent(): self { $activeSheet = $this->getActiveSheet(); - $selectedCell = Functions::trimSheetFromCellReference($this->getActiveCell()); // e.g. 'A1' + $selectedCell = $this->getActiveCell(); // e.g. 'A1' if ($activeSheet->cellExists($selectedCell)) { $xfIndex = $activeSheet->getCell($selectedCell)->getXfIndex(); @@ -206,15 +203,8 @@ class Style extends Supervisor if ($this->isSupervisor) { $pRange = $this->getSelectedCells(); - // Uppercase coordinate and strip any Worksheet reference from the selected range + // Uppercase coordinate $pRange = strtoupper($pRange); - if (strpos($pRange, '!') !== false) { - $pRangeWorksheet = StringHelper::strToUpper(trim(substr($pRange, 0, (int) strrpos($pRange, '!')), "'")); - if ($pRangeWorksheet !== '' && StringHelper::strToUpper($this->getActiveSheet()->getTitle()) !== $pRangeWorksheet) { - throw new Exception('Invalid Worksheet for specified Range'); - } - $pRange = strtoupper(Functions::trimSheetFromCellReference($pRange)); - } // Is it a cell range or a single cell? if (strpos($pRange, ':') === false) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Theme.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Theme.php deleted file mode 100644 index ab101f01e..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Theme.php +++ /dev/null @@ -1,269 +0,0 @@ - '000000', - 'lt1' => 'FFFFFF', - 'dk2' => '44546A', - 'lt2' => 'E7E6E6', - 'accent1' => '4472C4', - 'accent2' => 'ED7D31', - 'accent3' => 'A5A5A5', - 'accent4' => 'FFC000', - 'accent5' => '5B9BD5', - 'accent6' => '70AD47', - 'hlink' => '0563C1', - 'folHlink' => '954F72', - ]; - - public const COLOR_SCHEME_2007_2010_NAME = 'Office 2007-2010'; - public const COLOR_SCHEME_2007_2010 = [ - 'dk1' => '000000', - 'lt1' => 'FFFFFF', - 'dk2' => '1F497D', - 'lt2' => 'EEECE1', - 'accent1' => '4F81BD', - 'accent2' => 'C0504D', - 'accent3' => '9BBB59', - 'accent4' => '8064A2', - 'accent5' => '4BACC6', - 'accent6' => 'F79646', - 'hlink' => '0000FF', - 'folHlink' => '800080', - ]; - - /** @var string[] */ - private $themeColors = self::COLOR_SCHEME_2007_2010; - - /** @var string */ - private $majorFontLatin = 'Cambria'; - - /** @var string */ - private $majorFontEastAsian = ''; - - /** @var string */ - private $majorFontComplexScript = ''; - - /** @var string */ - private $minorFontLatin = 'Calibri'; - - /** @var string */ - private $minorFontEastAsian = ''; - - /** @var string */ - private $minorFontComplexScript = ''; - - /** - * Map of Major (header) fonts to write. - * - * @var string[] - */ - private $majorFontSubstitutions = self::FONTS_TIMES_SUBSTITUTIONS; - - /** - * Map of Minor (body) fonts to write. - * - * @var string[] - */ - private $minorFontSubstitutions = self::FONTS_ARIAL_SUBSTITUTIONS; - - public const FONTS_TIMES_SUBSTITUTIONS = [ - 'Jpan' => 'MS Pゴシック', - 'Hang' => '맑은 고딕', - 'Hans' => '宋体', - 'Hant' => '新細明體', - 'Arab' => 'Times New Roman', - 'Hebr' => 'Times New Roman', - 'Thai' => 'Tahoma', - 'Ethi' => 'Nyala', - 'Beng' => 'Vrinda', - 'Gujr' => 'Shruti', - 'Khmr' => 'MoolBoran', - 'Knda' => 'Tunga', - 'Guru' => 'Raavi', - 'Cans' => 'Euphemia', - 'Cher' => 'Plantagenet Cherokee', - 'Yiii' => 'Microsoft Yi Baiti', - 'Tibt' => 'Microsoft Himalaya', - 'Thaa' => 'MV Boli', - 'Deva' => 'Mangal', - 'Telu' => 'Gautami', - 'Taml' => 'Latha', - 'Syrc' => 'Estrangelo Edessa', - 'Orya' => 'Kalinga', - 'Mlym' => 'Kartika', - 'Laoo' => 'DokChampa', - 'Sinh' => 'Iskoola Pota', - 'Mong' => 'Mongolian Baiti', - 'Viet' => 'Times New Roman', - 'Uigh' => 'Microsoft Uighur', - 'Geor' => 'Sylfaen', - ]; - - public const FONTS_ARIAL_SUBSTITUTIONS = [ - 'Jpan' => 'MS Pゴシック', - 'Hang' => '맑은 고딕', - 'Hans' => '宋体', - 'Hant' => '新細明體', - 'Arab' => 'Arial', - 'Hebr' => 'Arial', - 'Thai' => 'Tahoma', - 'Ethi' => 'Nyala', - 'Beng' => 'Vrinda', - 'Gujr' => 'Shruti', - 'Khmr' => 'DaunPenh', - 'Knda' => 'Tunga', - 'Guru' => 'Raavi', - 'Cans' => 'Euphemia', - 'Cher' => 'Plantagenet Cherokee', - 'Yiii' => 'Microsoft Yi Baiti', - 'Tibt' => 'Microsoft Himalaya', - 'Thaa' => 'MV Boli', - 'Deva' => 'Mangal', - 'Telu' => 'Gautami', - 'Taml' => 'Latha', - 'Syrc' => 'Estrangelo Edessa', - 'Orya' => 'Kalinga', - 'Mlym' => 'Kartika', - 'Laoo' => 'DokChampa', - 'Sinh' => 'Iskoola Pota', - 'Mong' => 'Mongolian Baiti', - 'Viet' => 'Arial', - 'Uigh' => 'Microsoft Uighur', - 'Geor' => 'Sylfaen', - ]; - - public function getThemeColors(): array - { - return $this->themeColors; - } - - public function setThemeColor(string $key, string $value): self - { - $this->themeColors[$key] = $value; - - return $this; - } - - public function getThemeColorName(): string - { - return $this->themeColorName; - } - - public function setThemeColorName(string $name, ?array $themeColors = null): self - { - $this->themeColorName = $name; - if ($name === self::COLOR_SCHEME_2007_2010_NAME) { - $themeColors = $themeColors ?? self::COLOR_SCHEME_2007_2010; - } elseif ($name === self::COLOR_SCHEME_2013_PLUS_NAME) { - $themeColors = $themeColors ?? self::COLOR_SCHEME_2013_PLUS; - } - if ($themeColors !== null) { - $this->themeColors = $themeColors; - } - - return $this; - } - - public function getMajorFontLatin(): string - { - return $this->majorFontLatin; - } - - public function getMajorFontEastAsian(): string - { - return $this->majorFontEastAsian; - } - - public function getMajorFontComplexScript(): string - { - return $this->majorFontComplexScript; - } - - public function getMajorFontSubstitutions(): array - { - return $this->majorFontSubstitutions; - } - - /** @param null|array $substitutions */ - public function setMajorFontValues(?string $latin, ?string $eastAsian, ?string $complexScript, $substitutions): self - { - if (!empty($latin)) { - $this->majorFontLatin = $latin; - } - if ($eastAsian !== null) { - $this->majorFontEastAsian = $eastAsian; - } - if ($complexScript !== null) { - $this->majorFontComplexScript = $complexScript; - } - if ($substitutions !== null) { - $this->majorFontSubstitutions = $substitutions; - } - - return $this; - } - - public function getMinorFontLatin(): string - { - return $this->minorFontLatin; - } - - public function getMinorFontEastAsian(): string - { - return $this->minorFontEastAsian; - } - - public function getMinorFontComplexScript(): string - { - return $this->minorFontComplexScript; - } - - public function getMinorFontSubstitutions(): array - { - return $this->minorFontSubstitutions; - } - - /** @param null|array $substitutions */ - public function setMinorFontValues(?string $latin, ?string $eastAsian, ?string $complexScript, $substitutions): self - { - if (!empty($latin)) { - $this->minorFontLatin = $latin; - } - if ($eastAsian !== null) { - $this->minorFontEastAsian = $eastAsian; - } - if ($complexScript !== null) { - $this->minorFontComplexScript = $complexScript; - } - if ($substitutions !== null) { - $this->minorFontSubstitutions = $substitutions; - } - - return $this; - } - - public function getThemeFontName(): string - { - return $this->themeFontName; - } - - public function setThemeFontName(?string $name): self - { - if (!empty($name)) { - $this->themeFontName = $name; - } - - return $this; - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php index cbc4ff65f..d6041985d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php @@ -321,7 +321,7 @@ class AutoFilter * * @return bool */ - protected static function filterTestInSimpleDataSet($cellValue, $dataSet) + private static function filterTestInSimpleDataSet($cellValue, $dataSet) { $dataSetValues = $dataSet['filterValues']; $blanks = $dataSet['blanks']; @@ -340,7 +340,7 @@ class AutoFilter * * @return bool */ - protected static function filterTestInDateGroupSet($cellValue, $dataSet) + private static function filterTestInDateGroupSet($cellValue, $dataSet) { $dateSet = $dataSet['filterValues']; $blanks = $dataSet['blanks']; @@ -384,7 +384,7 @@ class AutoFilter * * @return bool */ - protected static function filterTestInCustomDataSet($cellValue, $ruleSet) + private static function filterTestInCustomDataSet($cellValue, $ruleSet) { /** @var array[] */ $dataSet = $ruleSet['filterRules']; @@ -509,7 +509,7 @@ class AutoFilter * * @return bool */ - protected static function filterTestInPeriodDateSet($cellValue, $monthSet) + private static function filterTestInPeriodDateSet($cellValue, $monthSet) { // Blank cells are always ignored, so return a FALSE if (($cellValue == '') || ($cellValue === null)) { diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php index d51023fcc..34e1145e0 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php @@ -197,6 +197,21 @@ class PageMargins return $this; } + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } + public static function fromCentimeters(float $value): float { return $value / 2.54; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php index 72c8958c8..22c99ff3b 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php @@ -885,4 +885,19 @@ class PageSetup return $this; } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php index 697f11c2a..13464c997 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php @@ -175,4 +175,19 @@ class SheetView return $this; } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table.php index 1bc8dff45..dc2a4f8a5 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table.php @@ -180,7 +180,7 @@ class Table private function updateStructuredReferencesInCells(Worksheet $worksheet, string $newName): void { - $pattern = '/' . preg_quote($this->name, '/') . '\[/mui'; + $pattern = '/' . preg_quote($this->name) . '\[/mui'; foreach ($worksheet->getCoordinates(false) as $coordinate) { $cell = $worksheet->getCell($coordinate); @@ -196,7 +196,7 @@ class Table private function updateStructuredReferencesInNamedFormulae(Spreadsheet $spreadsheet, string $newName): void { - $pattern = '/' . preg_quote($this->name, '/') . '\[/mui'; + $pattern = '/' . preg_quote($this->name) . '\[/mui'; foreach ($spreadsheet->getNamedFormulae() as $namedFormula) { $formula = $namedFormula->getValue(); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/Column.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/Column.php index 32dd4c4f8..30630c0d4 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/Column.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/Column.php @@ -225,7 +225,7 @@ class Column private static function updateStructuredReferencesInCells(Worksheet $worksheet, string $oldTitle, string $newTitle): void { - $pattern = '/\[(@?)' . preg_quote($oldTitle, '/') . '\]/mui'; + $pattern = '/\[(@?)' . preg_quote($oldTitle) . '\]/mui'; foreach ($worksheet->getCoordinates(false) as $coordinate) { $cell = $worksheet->getCell($coordinate); @@ -241,7 +241,7 @@ class Column private static function updateStructuredReferencesInNamedFormulae(Spreadsheet $spreadsheet, string $oldTitle, string $newTitle): void { - $pattern = '/\[(@?)' . preg_quote($oldTitle, '/') . '\]/mui'; + $pattern = '/\[(@?)' . preg_quote($oldTitle) . '\]/mui'; foreach ($spreadsheet->getNamedFormulae() as $namedFormula) { $formula = $namedFormula->getValue(); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Validations.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Validations.php index 42ba566c6..aab3aae44 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Validations.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Validations.php @@ -53,9 +53,6 @@ class Validations return self::validateCellRange($cellRange); } - private const SETMAXROW = '${1}1:${2}' . AddressRange::MAX_ROW; - private const SETMAXCOL = 'A${1}:' . AddressRange::MAX_COLUMN . '${2}'; - /** * Validate a cell range. * @@ -72,7 +69,7 @@ class Validations // or Row ranges like '1:3' to 'A1:XFD3' $addressRange = (string) preg_replace( ['/^([A-Z]+):([A-Z]+)$/i', '/^(\\d+):(\\d+)$/'], - [self::SETMAXROW, self::SETMAXCOL], + ['${1}1:${2}1048576', 'A${1}:XFD${2}'], $addressRange ); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php index 29221e991..cc0e05b69 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -543,18 +543,9 @@ class Worksheet implements IComparable */ public function getColumnDimensions() { - /** @var callable */ - $callable = [self::class, 'columnDimensionCompare']; - uasort($this->columnDimensions, $callable); - return $this->columnDimensions; } - private static function columnDimensionCompare(ColumnDimension $a, ColumnDimension $b): int - { - return $a->getColumnNumeric() - $b->getColumnNumeric(); - } - /** * Get default column dimension. * @@ -1815,15 +1806,9 @@ class Worksheet implements IComparable public function getBreaks() { $breaks = []; - /** @var callable */ - $compareFunction = [self::class, 'compareRowBreaks']; - uksort($this->rowBreaks, $compareFunction); foreach ($this->rowBreaks as $break) { $breaks[$break->getCoordinate()] = self::BREAK_ROW; } - /** @var callable */ - $compareFunction = [self::class, 'compareColumnBreaks']; - uksort($this->columnBreaks, $compareFunction); foreach ($this->columnBreaks as $break) { $breaks[$break->getCoordinate()] = self::BREAK_COLUMN; } @@ -1838,40 +1823,16 @@ class Worksheet implements IComparable */ public function getRowBreaks() { - /** @var callable */ - $compareFunction = [self::class, 'compareRowBreaks']; - uksort($this->rowBreaks, $compareFunction); - return $this->rowBreaks; } - protected static function compareRowBreaks(string $coordinate1, string $coordinate2): int - { - $row1 = Coordinate::indexesFromString($coordinate1)[1]; - $row2 = Coordinate::indexesFromString($coordinate2)[1]; - - return $row1 - $row2; - } - - protected static function compareColumnBreaks(string $coordinate1, string $coordinate2): int - { - $column1 = Coordinate::indexesFromString($coordinate1)[0]; - $column2 = Coordinate::indexesFromString($coordinate2)[0]; - - return $column1 - $column2; - } - /** - * Get column breaks. + * Get row breaks. * * @return PageBreak[] */ public function getColumnBreaks() { - /** @var callable */ - $compareFunction = [self::class, 'compareColumnBreaks']; - uksort($this->columnBreaks, $compareFunction); - return $this->columnBreaks; } @@ -2487,12 +2448,12 @@ class Worksheet implements IComparable /** * Insert a new row, updating all possible related data. * - * @param int $before Insert before this row number - * @param int $numberOfRows Number of new rows to insert + * @param int $before Insert before this one + * @param int $numberOfRows Number of rows to insert * * @return $this */ - public function insertNewRowBefore(int $before, int $numberOfRows = 1) + public function insertNewRowBefore($before, $numberOfRows = 1) { if ($before >= 1) { $objReferenceHelper = ReferenceHelper::getInstance(); @@ -2507,12 +2468,12 @@ class Worksheet implements IComparable /** * Insert a new column, updating all possible related data. * - * @param string $before Insert before this column Name, eg: 'A' - * @param int $numberOfColumns Number of new columns to insert + * @param string $before Insert before this one, eg: 'A' + * @param int $numberOfColumns Number of columns to insert * * @return $this */ - public function insertNewColumnBefore(string $before, int $numberOfColumns = 1) + public function insertNewColumnBefore($before, $numberOfColumns = 1) { if (!is_numeric($before)) { $objReferenceHelper = ReferenceHelper::getInstance(); @@ -2527,12 +2488,12 @@ class Worksheet implements IComparable /** * Insert a new column, updating all possible related data. * - * @param int $beforeColumnIndex Insert before this column ID (numeric column coordinate of the cell) - * @param int $numberOfColumns Number of new columns to insert + * @param int $beforeColumnIndex Insert before this one (numeric column coordinate of the cell) + * @param int $numberOfColumns Number of columns to insert * * @return $this */ - public function insertNewColumnBeforeByIndex(int $beforeColumnIndex, int $numberOfColumns = 1) + public function insertNewColumnBeforeByIndex($beforeColumnIndex, $numberOfColumns = 1) { if ($beforeColumnIndex >= 1) { return $this->insertNewColumnBefore(Coordinate::stringFromColumnIndex($beforeColumnIndex), $numberOfColumns); @@ -2544,12 +2505,12 @@ class Worksheet implements IComparable /** * Delete a row, updating all possible related data. * - * @param int $row Remove rows, starting with this row number + * @param int $row Remove starting with this one * @param int $numberOfRows Number of rows to remove * * @return $this */ - public function removeRow(int $row, int $numberOfRows = 1) + public function removeRow($row, $numberOfRows = 1) { if ($row < 1) { throw new Exception('Rows to be deleted should at least start from row 1.'); @@ -2600,12 +2561,12 @@ class Worksheet implements IComparable /** * Remove a column, updating all possible related data. * - * @param string $column Remove columns starting with this column name, eg: 'A' + * @param string $column Remove starting with this one, eg: 'A' * @param int $numberOfColumns Number of columns to remove * * @return $this */ - public function removeColumn(string $column, int $numberOfColumns = 1) + public function removeColumn($column, $numberOfColumns = 1) { if (is_numeric($column)) { throw new Exception('Column references should not be numeric.'); @@ -2662,12 +2623,12 @@ class Worksheet implements IComparable /** * Remove a column, updating all possible related data. * - * @param int $columnIndex Remove starting with this column Index (numeric column coordinate) + * @param int $columnIndex Remove starting with this one (numeric column coordinate of the cell) * @param int $numColumns Number of columns to remove * * @return $this */ - public function removeColumnByIndex(int $columnIndex, int $numColumns = 1) + public function removeColumnByIndex($columnIndex, $numColumns = 1) { if ($columnIndex >= 1) { return $this->removeColumn(Coordinate::stringFromColumnIndex($columnIndex), $numColumns); @@ -3027,58 +2988,21 @@ class Worksheet implements IComparable return $this; } - /** - * @param mixed $nullValue - * - * @throws Exception - * @throws \PhpOffice\PhpSpreadsheet\Calculation\Exception - * - * @return mixed - */ - protected function cellToArray(Cell $cell, bool $calculateFormulas, bool $formatData, $nullValue) - { - $returnValue = $nullValue; - - if ($cell->getValue() !== null) { - if ($cell->getValue() instanceof RichText) { - $returnValue = $cell->getValue()->getPlainText(); - } else { - $returnValue = ($calculateFormulas) ? $cell->getCalculatedValue() : $cell->getValue(); - } - - if ($formatData) { - $style = $this->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex()); - $returnValue = NumberFormat::toFormattedString( - $returnValue, - $style->getNumberFormat()->getFormatCode() ?? NumberFormat::FORMAT_GENERAL - ); - } - } - - return $returnValue; - } - /** * Create array from a range of cells. * + * @param string $range Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist * @param bool $calculateFormulas Should formulas be calculated? * @param bool $formatData Should formatting be applied to cell values? * @param bool $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero - * True - Return rows and columns indexed by their actual row and column IDs - * @param bool $ignoreHidden False - Return values for rows/columns even if they are defined as hidden. - * True - Don't return values for rows/columns that are defined as hidden. + * True - Return rows and columns indexed by their actual row and column IDs + * + * @return array */ - public function rangeToArray( - string $range, - $nullValue = null, - bool $calculateFormulas = true, - bool $formatData = true, - bool $returnCellRef = false, - bool $ignoreHidden = false - ): array { - $range = Validations::validateCellOrCellRange($range); - + public function rangeToArray($range, $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) + { + // Returnvalue $returnValue = []; // Identify the range that we need to extract from the worksheet [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($range); @@ -3091,23 +3015,42 @@ class Worksheet implements IComparable // Loop through rows $r = -1; for ($row = $minRow; $row <= $maxRow; ++$row) { - if (($ignoreHidden === true) && ($this->getRowDimension($row)->getVisible() === false)) { - continue; - } - $rowRef = $returnCellRef ? $row : ++$r; + $rRef = $returnCellRef ? $row : ++$r; $c = -1; // Loop through columns in the current row - for ($col = $minCol; $col !== $maxCol; ++$col) { - if (($ignoreHidden === true) && ($this->getColumnDimension($col)->getVisible() === false)) { - continue; - } - $columnRef = $returnCellRef ? $col : ++$c; + for ($col = $minCol; $col != $maxCol; ++$col) { + $cRef = $returnCellRef ? $col : ++$c; // Using getCell() will create a new cell if it doesn't already exist. We don't want that to happen // so we test and retrieve directly against cellCollection - $cell = $this->cellCollection->get("{$col}{$row}"); - $returnValue[$rowRef][$columnRef] = $nullValue; + $cell = $this->cellCollection->get($col . $row); + //if ($this->cellCollection->has($col . $row)) { if ($cell !== null) { - $returnValue[$rowRef][$columnRef] = $this->cellToArray($cell, $calculateFormulas, $formatData, $nullValue); + // Cell exists + if ($cell->getValue() !== null) { + if ($cell->getValue() instanceof RichText) { + $returnValue[$rRef][$cRef] = $cell->getValue()->getPlainText(); + } else { + if ($calculateFormulas) { + $returnValue[$rRef][$cRef] = $cell->getCalculatedValue(); + } else { + $returnValue[$rRef][$cRef] = $cell->getValue(); + } + } + + if ($formatData) { + $style = $this->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex()); + $returnValue[$rRef][$cRef] = NumberFormat::toFormattedString( + $returnValue[$rRef][$cRef], + $style->getNumberFormat()->getFormatCode() ?? NumberFormat::FORMAT_GENERAL + ); + } + } else { + // Cell holds a NULL + $returnValue[$rRef][$cRef] = $nullValue; + } + } else { + // Cell doesn't exist + $returnValue[$rRef][$cRef] = $nullValue; } } } @@ -3159,18 +3102,12 @@ class Worksheet implements IComparable * @param bool $calculateFormulas Should formulas be calculated? * @param bool $formatData Should formatting be applied to cell values? * @param bool $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero - * True - Return rows and columns indexed by their actual row and column IDs - * @param bool $ignoreHidden False - Return values for rows/columns even if they are defined as hidden. - * True - Don't return values for rows/columns that are defined as hidden. + * True - Return rows and columns indexed by their actual row and column IDs + * + * @return array */ - public function namedRangeToArray( - string $definedName, - $nullValue = null, - bool $calculateFormulas = true, - bool $formatData = true, - bool $returnCellRef = false, - bool $ignoreHidden = false - ): array { + public function namedRangeToArray(string $definedName, $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) + { $retVal = []; $namedRange = $this->validateNamedRange($definedName); if ($namedRange !== null) { @@ -3178,7 +3115,7 @@ class Worksheet implements IComparable $cellRange = str_replace('$', '', $cellRange); $workSheet = $namedRange->getWorksheet(); if ($workSheet !== null) { - $retVal = $workSheet->rangeToArray($cellRange, $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden); + $retVal = $workSheet->rangeToArray($cellRange, $nullValue, $calculateFormulas, $formatData, $returnCellRef); } } @@ -3192,17 +3129,12 @@ class Worksheet implements IComparable * @param bool $calculateFormulas Should formulas be calculated? * @param bool $formatData Should formatting be applied to cell values? * @param bool $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero - * True - Return rows and columns indexed by their actual row and column IDs - * @param bool $ignoreHidden False - Return values for rows/columns even if they are defined as hidden. - * True - Don't return values for rows/columns that are defined as hidden. + * True - Return rows and columns indexed by their actual row and column IDs + * + * @return array */ - public function toArray( - $nullValue = null, - bool $calculateFormulas = true, - bool $formatData = true, - bool $returnCellRef = false, - bool $ignoreHidden = false - ): array { + public function toArray($nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) + { // Garbage collect... $this->garbageCollect(); @@ -3211,7 +3143,7 @@ class Worksheet implements IComparable $maxRow = $this->getHighestRow(); // Return - return $this->rangeToArray("A1:{$maxCol}{$maxRow}", $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden); + return $this->rangeToArray('A1:' . $maxCol . $maxRow, $nullValue, $calculateFormulas, $formatData, $returnCellRef); } /** diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php index 842998f9e..c30bb30ac 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php @@ -7,11 +7,9 @@ use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Chart\Chart; -use PhpOffice\PhpSpreadsheet\Document\Properties; use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\RichText\Run; use PhpOffice\PhpSpreadsheet\Settings; -use PhpOffice\PhpSpreadsheet\Shared\Date; use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing; use PhpOffice\PhpSpreadsheet\Shared\File; use PhpOffice\PhpSpreadsheet\Shared\Font as SharedFont; @@ -344,21 +342,13 @@ class Html extends BaseWriter private static function generateMeta(?string $val, string $desc): string { - return ($val || $val === '0') + return $val ? (' ' . PHP_EOL) : ''; } public const BODY_LINE = ' ' . PHP_EOL; - private const CUSTOM_TO_META = [ - Properties::PROPERTY_TYPE_BOOLEAN => 'bool', - Properties::PROPERTY_TYPE_DATE => 'date', - Properties::PROPERTY_TYPE_FLOAT => 'float', - Properties::PROPERTY_TYPE_INTEGER => 'int', - Properties::PROPERTY_TYPE_STRING => 'string', - ]; - /** * Generate HTML header. * @@ -384,36 +374,6 @@ class Html extends BaseWriter $html .= self::generateMeta($properties->getCategory(), 'category'); $html .= self::generateMeta($properties->getCompany(), 'company'); $html .= self::generateMeta($properties->getManager(), 'manager'); - $html .= self::generateMeta($properties->getLastModifiedBy(), 'lastModifiedBy'); - $date = Date::dateTimeFromTimestamp((string) $properties->getCreated()); - $date->setTimeZone(Date::getDefaultOrLocalTimeZone()); - $html .= self::generateMeta($date->format(DATE_W3C), 'created'); - $date = Date::dateTimeFromTimestamp((string) $properties->getModified()); - $date->setTimeZone(Date::getDefaultOrLocalTimeZone()); - $html .= self::generateMeta($date->format(DATE_W3C), 'modified'); - - $customProperties = $properties->getCustomProperties(); - foreach ($customProperties as $customProperty) { - $propertyValue = $properties->getCustomPropertyValue($customProperty); - $propertyType = $properties->getCustomPropertyType($customProperty); - $propertyQualifier = self::CUSTOM_TO_META[$propertyType] ?? null; - if ($propertyQualifier !== null) { - if ($propertyType === Properties::PROPERTY_TYPE_BOOLEAN) { - $propertyValue = $propertyValue ? '1' : '0'; - } elseif ($propertyType === Properties::PROPERTY_TYPE_DATE) { - $date = Date::dateTimeFromTimestamp((string) $propertyValue); - $date->setTimeZone(Date::getDefaultOrLocalTimeZone()); - $propertyValue = $date->format(DATE_W3C); - } else { - $propertyValue = (string) $propertyValue; - } - $html .= self::generateMeta($propertyValue, "custom.$propertyQualifier.$customProperty"); - } - } - - if (!empty($properties->getHyperlinkBase())) { - $html .= ' ' . PHP_EOL; - } $html .= $includeStyles ? $this->generateStyles(true) : $this->generatePageDeclarations(true); @@ -733,8 +693,7 @@ class Html extends BaseWriter // max-width: 100% ensures that image doesnt overflow containing cell // width: X sets width of supplied image. // As a result, images bigger than cell will be contained and images smaller will not get stretched - $html .= '' . $filedesc . ''; + $html .= '' . $filedesc . ''; } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php index c9e0ba839..872be52de 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php @@ -12,6 +12,7 @@ use PhpOffice\PhpSpreadsheet\Writer\Ods\Settings; use PhpOffice\PhpSpreadsheet\Writer\Ods\Styles; use PhpOffice\PhpSpreadsheet\Writer\Ods\Thumbnails; use ZipStream\Exception\OverflowException; +use ZipStream\Option\Archive; use ZipStream\ZipStream; class Ods extends BaseWriter @@ -157,7 +158,11 @@ class Ods extends BaseWriter } // Create new ZIP stream - return ZipStream0::newZipStream($this->fileHandle); + $options = new Archive(); + $options->setEnableZip64(false); + $options->setOutputStream($this->fileHandle); + + return new ZipStream(null, $options); } /** diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php index e0a729ab8..e931421af 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php @@ -126,16 +126,7 @@ class Content extends WriterPart $objWriter->writeAttribute('table:name', $spreadsheet->getSheet($sheetIndex)->getTitle()); $objWriter->writeAttribute('table:style-name', Style::TABLE_STYLE_PREFIX . (string) ($sheetIndex + 1)); $objWriter->writeElement('office:forms'); - $lastColumn = 0; foreach ($spreadsheet->getSheet($sheetIndex)->getColumnDimensions() as $columnDimension) { - $thisColumn = $columnDimension->getColumnNumeric(); - $emptyColumns = $thisColumn - $lastColumn - 1; - if ($emptyColumns > 0) { - $objWriter->startElement('table:table-column'); - $objWriter->writeAttribute('table:number-columns-repeated', (string) $emptyColumns); - $objWriter->endElement(); - } - $lastColumn = $thisColumn; $objWriter->startElement('table:table-column'); $objWriter->writeAttribute( 'table:style-name', diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php index 983414fcc..33a404d42 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php @@ -751,12 +751,11 @@ class Xls extends BaseWriter $dataSection_Content .= $dataProp['data']['data']; $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']); - /* Condition below can never be true - } elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) - $dataSection_Content .= $dataProp['data']['data']; + // Condition below can never be true + //} elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + // $dataSection_Content .= $dataProp['data']['data']; - $dataSection_Content_Offset += 4 + 8; - */ + // $dataSection_Content_Offset += 4 + 8; } else { $dataSection_Content .= $dataProp['data']['data']; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php index f195ac782..6b98395f5 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php @@ -643,6 +643,7 @@ class Parser // TODO: use real error codes throw new WriterException('Unknown range separator'); } + // Convert the cell references [$row1, $col1] = $this->cellToPackedRowcol($cell1); [$row2, $col2] = $this->cellToPackedRowcol($cell2); @@ -1108,8 +1109,8 @@ class Parser if (is_numeric($token) && (!is_numeric($token . $this->lookAhead) || ($this->lookAhead == '')) && ($this->lookAhead !== '!') && ($this->lookAhead !== ':')) { return $token; } + // If it's a string (of maximum 255 characters) if (preg_match('/"([^"]|""){0,255}"/', $token) && $this->lookAhead !== '"' && (substr_count($token, '"') % 2 == 0)) { - // If it's a string (of maximum 255 characters) return $token; } // If it's an error code @@ -1218,18 +1219,21 @@ class Parser $this->advance(); return $result; - } elseif (preg_match('/^#[A-Z0\\/]{3,5}[!?]{1}$/', $this->currentToken) || $this->currentToken == '#N/A') { // error code + // If it's an error code + } elseif (preg_match('/^#[A-Z0\\/]{3,5}[!?]{1}$/', $this->currentToken) || $this->currentToken == '#N/A') { $result = $this->createTree($this->currentToken, 'ptgErr', ''); $this->advance(); return $result; - } elseif ($this->currentToken == '-') { // negative value + // If it's a negative value + } elseif ($this->currentToken == '-') { // catch "-" Term $this->advance(); $result2 = $this->expression(); return $this->createTree('ptgUminus', $result2, ''); - } elseif ($this->currentToken == '+') { // positive value + // If it's a positive value + } elseif ($this->currentToken == '+') { // catch "+" Term $this->advance(); $result2 = $this->expression(); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Workbook.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Workbook.php index 3c68847aa..6e9b265dc 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Workbook.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Workbook.php @@ -643,8 +643,9 @@ class Workbook extends BIFFwriter // store the DEFINEDNAME record $chunk .= $this->writeData($this->writeDefinedNameBiff8(pack('C', 0x07), $formulaData, $i + 1, true)); + + // (exclusive) either repeatColumns or repeatRows } elseif ($sheetSetup->isColumnsToRepeatAtLeftSet() || $sheetSetup->isRowsToRepeatAtTopSet()) { - // (exclusive) either repeatColumns or repeatRows. // Columns to repeat if ($sheetSetup->isColumnsToRepeatAtLeftSet()) { $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); @@ -1101,15 +1102,16 @@ class Workbook extends BIFFwriter // 2. space remaining is greater than or equal to minimum space needed // here we write as much as we can in the current block, then move to next record data block + // 1. space remaining is less than minimum space needed if ($space_remaining < $min_space_needed) { - // 1. space remaining is less than minimum space needed. // we close the block, store the block data $recordDatas[] = $recordData; // and start new record data block where we start writing the string $recordData = ''; + + // 2. space remaining is greater than or equal to minimum space needed } else { - // 2. space remaining is greater than or equal to minimum space needed. // initialize effective remaining space, for Unicode strings this may need to be reduced by 1, see below $effective_space_remaining = $space_remaining; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index aeedd08e7..9f23bd365 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -503,8 +503,6 @@ class Worksheet extends BIFFwriter $this->writeMergedCells(); // Hyperlinks - $phpParent = $phpSheet->getParent(); - $hyperlinkbase = ($phpParent === null) ? '' : $phpParent->getProperties()->getHyperlinkBase(); foreach ($phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) { [$column, $row] = Coordinate::indexesFromString($coordinate); @@ -515,11 +513,6 @@ class Worksheet extends BIFFwriter $url = str_replace('sheet://', 'internal:', $url); } elseif (preg_match('/^(http:|https:|ftp:|mailto:)/', $url)) { // URL - } elseif (!empty($hyperlinkbase) && preg_match('~^([A-Za-z]:)?[/\\\\]~', $url) !== 1) { - $url = "$hyperlinkbase$url"; - if (preg_match('/^(http:|https:|ftp:|mailto:)/', $url) !== 1) { - $url = 'external:' . $url; - } } else { // external (local file) $url = 'external:' . $url; diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php index 6ed12d4aa..07b790440 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php @@ -31,6 +31,7 @@ use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Workbook; use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet; use ZipArchive; use ZipStream\Exception\OverflowException; +use ZipStream\Option\Archive; use ZipStream\ZipStream; class Xlsx extends BaseWriter @@ -376,7 +377,7 @@ class Xlsx extends BaseWriter } // Add theme to ZIP file - $zipContent['xl/theme/theme1.xml'] = $this->getWriterPartTheme()->writeTheme($this->spreadSheet); + $zipContent['xl/theme/theme1.xml'] = $this->getWriterPartTheme()->writeTheme(); // Add string table to ZIP file $zipContent['xl/sharedStrings.xml'] = $this->getWriterPartStringTable()->writeStringTable($this->stringTable); @@ -545,7 +546,11 @@ class Xlsx extends BaseWriter $this->openFileHandle($filename); - $this->zip = ZipStream0::newZipStream($this->fileHandle); + $options = new Archive(); + $options->setEnableZip64(false); + $options->setOutputStream($this->fileHandle); + + $this->zip = new ZipStream(null, $options); $this->addZipFiles($zipContent); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php index 6d302aac4..6465904ee 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php @@ -14,7 +14,6 @@ use PhpOffice\PhpSpreadsheet\Chart\Title; use PhpOffice\PhpSpreadsheet\Chart\TrendLine; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces; use PhpOffice\PhpSpreadsheet\Shared\XMLWriter; -use PhpOffice\PhpSpreadsheet\Style\Font; use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException; class Chart extends WriterPart @@ -110,20 +109,12 @@ class Chart extends WriterPart $objWriter->endElement(); $objWriter->endElement(); // c:chart - - $objWriter->startElement('c:spPr'); if ($chart->getNoFill()) { + $objWriter->startElement('c:spPr'); $objWriter->startElement('a:noFill'); $objWriter->endElement(); // a:noFill + $objWriter->endElement(); // c:spPr } - $fillColor = $chart->getFillColor(); - if ($fillColor->isUsable()) { - $this->writeColor($objWriter, $fillColor); - } - $borderLines = $chart->getBorderLines(); - $this->writeLineStyles($objWriter, $borderLines); - $this->writeEffects($objWriter, $borderLines); - $objWriter->endElement(); // c:spPr $this->writePrintSettings($objWriter); @@ -210,17 +201,6 @@ class Chart extends WriterPart $objWriter->writeAttribute('val', ($legend->getOverlay()) ? '1' : '0'); $objWriter->endElement(); - $objWriter->startElement('c:spPr'); - $fillColor = $legend->getFillColor(); - if ($fillColor->isUsable()) { - $this->writeColor($objWriter, $fillColor); - } - $borderLines = $legend->getBorderLines(); - $this->writeLineStyles($objWriter, $borderLines); - $this->writeEffects($objWriter, $borderLines); - $objWriter->endElement(); // c:spPr - - $legendText = $legend->getLegendText(); $objWriter->startElement('c:txPr'); $objWriter->startElement('a:bodyPr'); $objWriter->endElement(); @@ -233,21 +213,17 @@ class Chart extends WriterPart $objWriter->writeAttribute('rtl', '0'); $objWriter->startElement('a:defRPr'); - if ($legendText !== null) { - $this->writeColor($objWriter, $legendText->getFillColorObject()); - $this->writeEffects($objWriter, $legendText); - } - $objWriter->endElement(); // a:defRpr - $objWriter->endElement(); // a:pPr + $objWriter->endElement(); + $objWriter->endElement(); $objWriter->startElement('a:endParaRPr'); $objWriter->writeAttribute('lang', 'en-US'); - $objWriter->endElement(); // a:endParaRPr + $objWriter->endElement(); - $objWriter->endElement(); // a:p - $objWriter->endElement(); // c:txPr + $objWriter->endElement(); + $objWriter->endElement(); - $objWriter->endElement(); // c:legend + $objWriter->endElement(); } /** @@ -331,26 +307,19 @@ class Chart extends WriterPart $objWriter->startElement('c:hiLowLines'); $objWriter->endElement(); - $gapWidth = $plotArea->getGapWidth(); - $upBars = $plotArea->getUseUpBars(); - $downBars = $plotArea->getUseDownBars(); - if ($gapWidth !== null || $upBars || $downBars) { - $objWriter->startElement('c:upDownBars'); - if ($gapWidth !== null) { - $objWriter->startElement('c:gapWidth'); - $objWriter->writeAttribute('val', "$gapWidth"); - $objWriter->endElement(); - } - if ($upBars) { - $objWriter->startElement('c:upBars'); - $objWriter->endElement(); - } - if ($downBars) { - $objWriter->startElement('c:downBars'); - $objWriter->endElement(); - } - $objWriter->endElement(); // c:upDownBars - } + $objWriter->startElement('c:upDownBars'); + + $objWriter->startElement('c:gapWidth'); + $objWriter->writeAttribute('val', '300'); + $objWriter->endElement(); + + $objWriter->startElement('c:upBars'); + $objWriter->endElement(); + + $objWriter->startElement('c:downBars'); + $objWriter->endElement(); + + $objWriter->endElement(); } // Generate 3 unique numbers to use for axId values @@ -459,8 +428,8 @@ class Chart extends WriterPart } $objWriter->endElement(); // c:spPr } - $labelFont = $chartLayout->getLabelFont(); - if ($labelFont !== null) { + $fontColor = $chartLayout->getLabelFontColor(); + if ($fontColor && $fontColor->isUsable()) { $objWriter->startElement('c:txPr'); $objWriter->startElement('a:bodyPr'); @@ -476,7 +445,14 @@ class Chart extends WriterPart $objWriter->startElement('a:lstStyle'); $objWriter->endElement(); // a:lstStyle - $this->writeLabelFont($objWriter, $labelFont, $chartLayout->getLabelEffects()); + + $objWriter->startElement('a:p'); + $objWriter->startElement('a:pPr'); + $objWriter->startElement('a:defRPr'); + $this->writeColor($objWriter, $fontColor); + $objWriter->endElement(); // a:defRPr + $objWriter->endElement(); // a:pPr + $objWriter->endElement(); // a:p $objWriter->endElement(); // c:txPr } @@ -632,24 +608,25 @@ class Chart extends WriterPart } $textRotation = $yAxis->getAxisOptionsProperty('textRotation'); - $axisText = $yAxis->getAxisText(); - - if ($axisText !== null || is_numeric($textRotation)) { + if (is_numeric($textRotation)) { $objWriter->startElement('c:txPr'); $objWriter->startElement('a:bodyPr'); - if (is_numeric($textRotation)) { - $objWriter->writeAttribute('rot', Properties::angleToXml((float) $textRotation)); - } + $objWriter->writeAttribute('rot', Properties::angleToXml((float) $textRotation)); $objWriter->endElement(); // a:bodyPr $objWriter->startElement('a:lstStyle'); $objWriter->endElement(); // a:lstStyle - $this->writeLabelFont($objWriter, ($axisText === null) ? null : $axisText->getFont(), $axisText); + $objWriter->startElement('a:p'); + $objWriter->startElement('a:pPr'); + $objWriter->startElement('a:defRPr'); + $objWriter->endElement(); // a:defRPr + $objWriter->endElement(); // a:pPr + $objWriter->endElement(); // a:p $objWriter->endElement(); // c:txPr } $objWriter->startElement('c:spPr'); $this->writeColor($objWriter, $yAxis->getFillColorObject()); - $this->writeLineStyles($objWriter, $yAxis, $yAxis->getNoFill()); + $this->writeLineStyles($objWriter, $yAxis); $this->writeEffects($objWriter, $yAxis); $objWriter->endElement(); // spPr @@ -849,26 +826,25 @@ class Chart extends WriterPart } $textRotation = $xAxis->getAxisOptionsProperty('textRotation'); - $axisText = $xAxis->getAxisText(); - - if ($axisText !== null || is_numeric($textRotation)) { + if (is_numeric($textRotation)) { $objWriter->startElement('c:txPr'); $objWriter->startElement('a:bodyPr'); - if (is_numeric($textRotation)) { - $objWriter->writeAttribute('rot', Properties::angleToXml((float) $textRotation)); - } + $objWriter->writeAttribute('rot', Properties::angleToXml((float) $textRotation)); $objWriter->endElement(); // a:bodyPr $objWriter->startElement('a:lstStyle'); $objWriter->endElement(); // a:lstStyle - - $this->writeLabelFont($objWriter, ($axisText === null) ? null : $axisText->getFont(), $axisText); - + $objWriter->startElement('a:p'); + $objWriter->startElement('a:pPr'); + $objWriter->startElement('a:defRPr'); + $objWriter->endElement(); // a:defRPr + $objWriter->endElement(); // a:pPr + $objWriter->endElement(); // a:p $objWriter->endElement(); // c:txPr } $objWriter->startElement('c:spPr'); $this->writeColor($objWriter, $xAxis->getFillColorObject()); - $this->writeLineStyles($objWriter, $xAxis, $xAxis->getNoFill()); + $this->writeLineStyles($objWriter, $xAxis); $this->writeEffects($objWriter, $xAxis); $objWriter->endElement(); //end spPr @@ -1079,6 +1055,14 @@ class Chart extends WriterPart $labelFill = $plotLabel->getFillColorObject(); $labelFill = ($labelFill instanceof ChartColor) ? $labelFill : null; } + if ($plotLabel && $groupType !== DataSeries::TYPE_LINECHART) { + $fillColor = $plotLabel->getFillColorObject(); + if ($fillColor !== null && !is_array($fillColor) && $fillColor->isUsable()) { + $objWriter->startElement('c:spPr'); + $this->writeColor($objWriter, $fillColor); + $objWriter->endElement(); // c:spPr + } + } // Values $plotSeriesValues = $plotGroup->getPlotValuesByIndex($plotSeriesIdx); @@ -1110,12 +1094,6 @@ class Chart extends WriterPart $plotSeriesValues !== false ) { $objWriter->startElement('c:spPr'); - if ($plotLabel && $groupType !== DataSeries::TYPE_LINECHART) { - $fillColor = $plotLabel->getFillColorObject(); - if ($fillColor !== null && !is_array($fillColor) && $fillColor->isUsable()) { - $this->writeColor($objWriter, $fillColor); - } - } $fillObject = $labelFill ?? $plotSeriesValues->getFillColorObject(); $callLineStyles = true; if ($fillObject instanceof ChartColor && $fillObject->isUsable()) { @@ -1420,7 +1398,7 @@ class Chart extends WriterPart $count = $plotSeriesValues->getPointCount(); $source = $plotSeriesValues->getDataSource(); $values = $plotSeriesValues->getDataValues(); - if ($count > 1 || ($count === 1 && array_key_exists(0, $values) && "=$source" !== (string) $values[0])) { + if ($count > 1 || ($count === 1 && "=$source" !== (string) $values[0])) { $objWriter->startElement('c:' . $dataType . 'Cache'); if (($groupType != DataSeries::TYPE_PIECHART) && ($groupType != DataSeries::TYPE_PIECHART_3D) && ($groupType != DataSeries::TYPE_DONUTCHART)) { @@ -1792,51 +1770,4 @@ class Chart extends WriterPart } } } - - private function writeLabelFont(XMLWriter $objWriter, ?Font $labelFont, ?Properties $axisText): void - { - $objWriter->startElement('a:p'); - $objWriter->startElement('a:pPr'); - $objWriter->startElement('a:defRPr'); - if ($labelFont !== null) { - $fontSize = $labelFont->getSize(); - if (is_numeric($fontSize)) { - $fontSize *= (($fontSize < 100) ? 100 : 1); - $objWriter->writeAttribute('sz', (string) $fontSize); - } - if ($labelFont->getBold() === true) { - $objWriter->writeAttribute('b', '1'); - } - if ($labelFont->getItalic() === true) { - $objWriter->writeAttribute('i', '1'); - } - $fontColor = $labelFont->getChartColor(); - if ($fontColor !== null) { - $this->writeColor($objWriter, $fontColor); - } - } - if ($axisText !== null) { - $this->writeEffects($objWriter, $axisText); - } - if ($labelFont !== null) { - if (!empty($labelFont->getLatin())) { - $objWriter->startElement('a:latin'); - $objWriter->writeAttribute('typeface', $labelFont->getLatin()); - $objWriter->endElement(); - } - if (!empty($labelFont->getEastAsian())) { - $objWriter->startElement('a:eastAsian'); - $objWriter->writeAttribute('typeface', $labelFont->getEastAsian()); - $objWriter->endElement(); - } - if (!empty($labelFont->getComplexScript())) { - $objWriter->startElement('a:complexScript'); - $objWriter->writeAttribute('typeface', $labelFont->getComplexScript()); - $objWriter->endElement(); - } - } - $objWriter->endElement(); // a:defRPr - $objWriter->endElement(); // a:pPr - $objWriter->endElement(); // a:p - } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php index 8c33f5932..8902826a1 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php @@ -93,9 +93,6 @@ class DocProps extends WriterPart // SharedDoc $objWriter->writeElement('SharedDoc', 'false'); - // HyperlinkBase - $objWriter->writeElement('HyperlinkBase', $spreadsheet->getProperties()->getHyperlinkBase()); - // HyperlinksChanged $objWriter->writeElement('HyperlinksChanged', 'false'); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/FunctionPrefix.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/FunctionPrefix.php index cf4f90693..ecc247d86 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/FunctionPrefix.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/FunctionPrefix.php @@ -4,7 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx; class FunctionPrefix { - const XLFNREGEXP = '/(?:_xlfn\.)?((?:_xlws\.)?\b(' + const XLFNREGEXP = '/(?:_xlfn\.)?((?:_xlws\.)?(' // functions added with Excel 2010 . 'beta[.]dist' . '|beta[.]inv' diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php index 29e95eb2f..7f623933c 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php @@ -64,7 +64,7 @@ class StringTable extends WriterPart /** * Write string table to XML format. * - * @param (RichText|string)[] $stringTable + * @param (string|RichText)[] $stringTable * * @return string XML Output */ @@ -226,10 +226,9 @@ class StringTable extends WriterPart if ($element->getFont() !== null) { // rPr $objWriter->startElement($prefix . 'rPr'); - $fontSize = $element->getFont()->getSize(); - if (is_numeric($fontSize)) { - $fontSize *= (($fontSize < 100) ? 100 : 1); - $objWriter->writeAttribute('sz', (string) $fontSize); + $size = $element->getFont()->getSize(); + if (is_numeric($size)) { + $objWriter->writeAttribute('sz', (string) (int) ($size * 100)); } // Bold diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php index baafdc334..0261f22e5 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php @@ -112,13 +112,8 @@ class Style extends WriterPart $objWriter->writeAttribute('count', (string) count($spreadsheet->getCellXfCollection())); // xf - $alignment = new Alignment(); - $defaultAlignHash = $alignment->getHashCode(); - if ($defaultAlignHash !== $spreadsheet->getDefaultStyle()->getAlignment()->getHashCode()) { - $defaultAlignHash = ''; - } foreach ($spreadsheet->getCellXfCollection() as $cellXf) { - $this->writeCellStyleXf($objWriter, $cellXf, $spreadsheet, $defaultAlignHash); + $this->writeCellStyleXf($objWriter, $cellXf, $spreadsheet); } $objWriter->endElement(); @@ -359,13 +354,6 @@ class Style extends WriterPart $objWriter->endElement(); } - if (!empty($font->getScheme())) { - $this->startFont($objWriter, $fontStarted); - $objWriter->startElement('scheme'); - $objWriter->writeAttribute('val', $font->getScheme()); - $objWriter->endElement(); - } - if ($fontStarted) { $objWriter->endElement(); } @@ -412,7 +400,7 @@ class Style extends WriterPart /** * Write Cell Style Xf. */ - private function writeCellStyleXf(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Style\Style $style, Spreadsheet $spreadsheet, string $defaultAlignHash): void + private function writeCellStyleXf(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Style\Style $style, Spreadsheet $spreadsheet): void { // xf $objWriter->startElement('xf'); @@ -436,11 +424,7 @@ class Style extends WriterPart $objWriter->writeAttribute('applyNumberFormat', ($spreadsheet->getDefaultStyle()->getNumberFormat()->getHashCode() != $style->getNumberFormat()->getHashCode()) ? '1' : '0'); $objWriter->writeAttribute('applyFill', ($spreadsheet->getDefaultStyle()->getFill()->getHashCode() != $style->getFill()->getHashCode()) ? '1' : '0'); $objWriter->writeAttribute('applyBorder', ($spreadsheet->getDefaultStyle()->getBorders()->getHashCode() != $style->getBorders()->getHashCode()) ? '1' : '0'); - if ($defaultAlignHash !== '' && $defaultAlignHash === $style->getAlignment()->getHashCode()) { - $applyAlignment = '0'; - } else { - $applyAlignment = '1'; - } + $applyAlignment = ($spreadsheet->getDefaultStyle()->getAlignment()->getHashCode() != $style->getAlignment()->getHashCode()) ? '1' : '0'; $objWriter->writeAttribute('applyAlignment', $applyAlignment); if ($style->getProtection()->getLocked() != Protection::PROTECTION_INHERIT || $style->getProtection()->getHidden() != Protection::PROTECTION_INHERIT) { $objWriter->writeAttribute('applyProtection', 'true'); diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php index 1e8ef5b43..9ff29d45d 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php @@ -4,17 +4,109 @@ namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces; use PhpOffice\PhpSpreadsheet\Shared\XMLWriter; -use PhpOffice\PhpSpreadsheet\Spreadsheet; -use PhpOffice\PhpSpreadsheet\Theme as SpreadsheetTheme; class Theme extends WriterPart { + /** + * Map of Major fonts to write. + * + * @var string[] + */ + private static $majorFonts = [ + 'Jpan' => 'MS Pゴシック', + 'Hang' => '맑은 고딕', + 'Hans' => '宋体', + 'Hant' => '新細明體', + 'Arab' => 'Times New Roman', + 'Hebr' => 'Times New Roman', + 'Thai' => 'Tahoma', + 'Ethi' => 'Nyala', + 'Beng' => 'Vrinda', + 'Gujr' => 'Shruti', + 'Khmr' => 'MoolBoran', + 'Knda' => 'Tunga', + 'Guru' => 'Raavi', + 'Cans' => 'Euphemia', + 'Cher' => 'Plantagenet Cherokee', + 'Yiii' => 'Microsoft Yi Baiti', + 'Tibt' => 'Microsoft Himalaya', + 'Thaa' => 'MV Boli', + 'Deva' => 'Mangal', + 'Telu' => 'Gautami', + 'Taml' => 'Latha', + 'Syrc' => 'Estrangelo Edessa', + 'Orya' => 'Kalinga', + 'Mlym' => 'Kartika', + 'Laoo' => 'DokChampa', + 'Sinh' => 'Iskoola Pota', + 'Mong' => 'Mongolian Baiti', + 'Viet' => 'Times New Roman', + 'Uigh' => 'Microsoft Uighur', + 'Geor' => 'Sylfaen', + ]; + + /** + * Map of Minor fonts to write. + * + * @var string[] + */ + private static $minorFonts = [ + 'Jpan' => 'MS Pゴシック', + 'Hang' => '맑은 고딕', + 'Hans' => '宋体', + 'Hant' => '新細明體', + 'Arab' => 'Arial', + 'Hebr' => 'Arial', + 'Thai' => 'Tahoma', + 'Ethi' => 'Nyala', + 'Beng' => 'Vrinda', + 'Gujr' => 'Shruti', + 'Khmr' => 'DaunPenh', + 'Knda' => 'Tunga', + 'Guru' => 'Raavi', + 'Cans' => 'Euphemia', + 'Cher' => 'Plantagenet Cherokee', + 'Yiii' => 'Microsoft Yi Baiti', + 'Tibt' => 'Microsoft Himalaya', + 'Thaa' => 'MV Boli', + 'Deva' => 'Mangal', + 'Telu' => 'Gautami', + 'Taml' => 'Latha', + 'Syrc' => 'Estrangelo Edessa', + 'Orya' => 'Kalinga', + 'Mlym' => 'Kartika', + 'Laoo' => 'DokChampa', + 'Sinh' => 'Iskoola Pota', + 'Mong' => 'Mongolian Baiti', + 'Viet' => 'Arial', + 'Uigh' => 'Microsoft Uighur', + 'Geor' => 'Sylfaen', + ]; + + /** + * Map of core colours. + * + * @var string[] + */ + private static $colourScheme = [ + 'dk2' => '1F497D', + 'lt2' => 'EEECE1', + 'accent1' => '4F81BD', + 'accent2' => 'C0504D', + 'accent3' => '9BBB59', + 'accent4' => '8064A2', + 'accent5' => '4BACC6', + 'accent6' => 'F79646', + 'hlink' => '0000FF', + 'folHlink' => '800080', + ]; + /** * Write theme to XML format. * * @return string XML Output */ - public function writeTheme(Spreadsheet $spreadsheet) + public function writeTheme() { // Create XML writer $objWriter = null; @@ -23,7 +115,6 @@ class Theme extends WriterPart } else { $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); } - $theme = $spreadsheet->getTheme(); // XML header $objWriter->startDocument('1.0', 'UTF-8', 'yes'); @@ -38,39 +129,50 @@ class Theme extends WriterPart // a:clrScheme $objWriter->startElement('a:clrScheme'); - $objWriter->writeAttribute('name', $theme->getThemeColorName()); + $objWriter->writeAttribute('name', 'Office'); - $this->writeColourScheme($objWriter, $theme); + // a:dk1 + $objWriter->startElement('a:dk1'); + + // a:sysClr + $objWriter->startElement('a:sysClr'); + $objWriter->writeAttribute('val', 'windowText'); + $objWriter->writeAttribute('lastClr', '000000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:lt1 + $objWriter->startElement('a:lt1'); + + // a:sysClr + $objWriter->startElement('a:sysClr'); + $objWriter->writeAttribute('val', 'window'); + $objWriter->writeAttribute('lastClr', 'FFFFFF'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:dk2 + $this->writeColourScheme($objWriter); $objWriter->endElement(); // a:fontScheme $objWriter->startElement('a:fontScheme'); - $objWriter->writeAttribute('name', $theme->getThemeFontName()); + $objWriter->writeAttribute('name', 'Office'); // a:majorFont $objWriter->startElement('a:majorFont'); - $this->writeFonts( - $objWriter, - $theme->getMajorFontLatin(), - $theme->getMajorFontEastAsian(), - $theme->getMajorFontComplexScript(), - $theme->getMajorFontSubstitutions() - ); - $objWriter->endElement(); // a:majorFont + $this->writeFonts($objWriter, 'Cambria', self::$majorFonts); + $objWriter->endElement(); // a:minorFont $objWriter->startElement('a:minorFont'); - $this->writeFonts( - $objWriter, - $theme->getMinorFontLatin(), - $theme->getMinorFontEastAsian(), - $theme->getMinorFontComplexScript(), - $theme->getMinorFontSubstitutions() - ); - $objWriter->endElement(); // a:minorFont + $this->writeFonts($objWriter, 'Calibri', self::$minorFonts); + $objWriter->endElement(); - $objWriter->endElement(); // a:fontScheme + $objWriter->endElement(); // a:fmtScheme $objWriter->startElement('a:fmtScheme'); @@ -684,7 +786,7 @@ class Theme extends WriterPart * * @param string[] $fontSet */ - private function writeFonts(XMLWriter $objWriter, string $latinFont, string $eastAsianFont, string $complexScriptFont, array $fontSet): void + private function writeFonts(XMLWriter $objWriter, string $latinFont, array $fontSet): void { // a:latin $objWriter->startElement('a:latin'); @@ -693,12 +795,12 @@ class Theme extends WriterPart // a:ea $objWriter->startElement('a:ea'); - $objWriter->writeAttribute('typeface', $eastAsianFont); + $objWriter->writeAttribute('typeface', ''); $objWriter->endElement(); // a:cs $objWriter->startElement('a:cs'); - $objWriter->writeAttribute('typeface', $complexScriptFont); + $objWriter->writeAttribute('typeface', ''); $objWriter->endElement(); foreach ($fontSet as $fontScript => $typeface) { @@ -712,33 +814,16 @@ class Theme extends WriterPart /** * Write colour scheme to XML format. */ - private function writeColourScheme(XMLWriter $objWriter, SpreadsheetTheme $theme): void + private function writeColourScheme(XMLWriter $objWriter): void { - $themeArray = $theme->getThemeColors(); - // a:dk1 - $objWriter->startElement('a:dk1'); - $objWriter->startElement('a:sysClr'); - $objWriter->writeAttribute('val', 'windowText'); - $objWriter->writeAttribute('lastClr', $themeArray['dk1'] ?? '000000'); - $objWriter->endElement(); // a:sysClr - $objWriter->endElement(); // a:dk1 + foreach (self::$colourScheme as $colourName => $colourValue) { + $objWriter->startElement('a:' . $colourName); - // a:lt1 - $objWriter->startElement('a:lt1'); - $objWriter->startElement('a:sysClr'); - $objWriter->writeAttribute('val', 'window'); - $objWriter->writeAttribute('lastClr', $themeArray['lt1'] ?? 'FFFFFF'); - $objWriter->endElement(); // a:sysClr - $objWriter->endElement(); // a:lt1 + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', $colourValue); + $objWriter->endElement(); - foreach ($themeArray as $colourName => $colourValue) { - if ($colourName !== 'dk1' && $colourName !== 'lt1') { - $objWriter->startElement('a:' . $colourName); - $objWriter->startElement('a:srgbClr'); - $objWriter->writeAttribute('val', $colourValue); - $objWriter->endElement(); // a:srgbClr - $objWriter->endElement(); // a:$colourName - } + $objWriter->endElement(); } } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index 5e453b3d8..53c451245 100644 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -18,18 +18,6 @@ use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as PhpspreadsheetWorksheet; class Worksheet extends WriterPart { - /** @var string */ - private $numberStoredAsText = ''; - - /** @var string */ - private $formula = ''; - - /** @var string */ - private $twoDigitTextYear = ''; - - /** @var string */ - private $evalError = ''; - /** * Write worksheet to XML format. * @@ -40,10 +28,6 @@ class Worksheet extends WriterPart */ public function writeWorksheet(PhpspreadsheetWorksheet $worksheet, $stringTable = [], $includeCharts = false) { - $this->numberStoredAsText = ''; - $this->formula = ''; - $this->twoDigitTextYear = ''; - $this->evalError = ''; // Create XML writer $objWriter = null; if ($this->getParentWriter()->getUseDiskCaching()) { @@ -134,9 +118,6 @@ class Worksheet extends WriterPart // AlternateContent $this->writeAlternateContent($objWriter, $worksheet); - // IgnoredErrors - $this->writeIgnoredErrors($objWriter); - // Table $this->writeTable($objWriter, $worksheet); @@ -150,32 +131,6 @@ class Worksheet extends WriterPart return $objWriter->getData(); } - private function writeIgnoredError(XMLWriter $objWriter, bool &$started, string $attr, string $cells): void - { - if ($cells !== '') { - if (!$started) { - $objWriter->startElement('ignoredErrors'); - $started = true; - } - $objWriter->startElement('ignoredError'); - $objWriter->writeAttribute('sqref', substr($cells, 1)); - $objWriter->writeAttribute($attr, '1'); - $objWriter->endElement(); - } - } - - private function writeIgnoredErrors(XMLWriter $objWriter): void - { - $started = false; - $this->writeIgnoredError($objWriter, $started, 'numberStoredAsText', $this->numberStoredAsText); - $this->writeIgnoredError($objWriter, $started, 'formula', $this->formula); - $this->writeIgnoredError($objWriter, $started, 'twoDigitTextYear', $this->twoDigitTextYear); - $this->writeIgnoredError($objWriter, $started, 'evalError', $this->evalError); - if ($started) { - $objWriter->endElement(); - } - } - /** * Write SheetPr. */ @@ -1179,20 +1134,7 @@ class Worksheet extends WriterPart array_pop($columnsInRow); foreach ($columnsInRow as $column) { // Write cell - $coord = "$column$currentRow"; - if ($worksheet->getCell($coord)->getIgnoredErrors()->getNumberStoredAsText()) { - $this->numberStoredAsText .= " $coord"; - } - if ($worksheet->getCell($coord)->getIgnoredErrors()->getFormula()) { - $this->formula .= " $coord"; - } - if ($worksheet->getCell($coord)->getIgnoredErrors()->getTwoDigitTextYear()) { - $this->twoDigitTextYear .= " $coord"; - } - if ($worksheet->getCell($coord)->getIgnoredErrors()->getEvalError()) { - $this->evalError .= " $coord"; - } - $this->writeCell($objWriter, $worksheet, $coord, $aFlippedStringTable); + $this->writeCell($objWriter, $worksheet, "{$column}{$currentRow}", $aFlippedStringTable); } } diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream0.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream0.php deleted file mode 100644 index 886731ca9..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream0.php +++ /dev/null @@ -1,17 +0,0 @@ -setEnableZip64(false); - $options->setOutputStream($fileHandle); - - return new ZipStream(null, $options); - } -} diff --git a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream3.php b/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream3.php deleted file mode 100644 index d9c8d0b16..000000000 --- a/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream3.php +++ /dev/null @@ -1,22 +0,0 @@ - */ const ALL = [ self::SSL, diff --git a/vendor/rmccue/requests/src/Cookie.php b/vendor/rmccue/requests/src/Cookie.php index 6f971d6db..ccbbc73db 100644 --- a/vendor/rmccue/requests/src/Cookie.php +++ b/vendor/rmccue/requests/src/Cookie.php @@ -36,8 +36,8 @@ class Cookie { /** * Cookie attributes * - * Valid keys are `'path'`, `'domain'`, `'expires'`, `'max-age'`, `'secure'` and - * `'httponly'`. + * Valid keys are (currently) path, domain, expires, max-age, secure and + * httponly. * * @var \WpOrg\Requests\Utility\CaseInsensitiveDictionary|array Array-like object */ @@ -46,7 +46,8 @@ class Cookie { /** * Cookie flags * - * Valid keys are `'creation'`, `'last-access'`, `'persistent'` and `'host-only'`. + * Valid keys are (currently) creation, last-access, persistent and + * host-only. * * @var array */ @@ -65,13 +66,11 @@ class Cookie { /** * Create a new cookie object * - * @param string $name The name of the cookie. - * @param string $value The value for the cookie. + * @param string $name + * @param string $value * @param array|\WpOrg\Requests\Utility\CaseInsensitiveDictionary $attributes Associative array of attribute data - * @param array $flags The flags for the cookie. - * Valid keys are `'creation'`, `'last-access'`, - * `'persistent'` and `'host-only'`. - * @param int|null $reference_time Reference time for relative calculations. + * @param array $flags + * @param int|null $reference_time * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $name argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $value argument is not a string. @@ -280,11 +279,7 @@ class Cookie { public function normalize() { foreach ($this->attributes as $key => $value) { $orig_value = $value; - - if (is_string($key)) { - $value = $this->normalize_attribute($key, $value); - } - + $value = $this->normalize_attribute($key, $value); if ($value === null) { unset($this->attributes[$key]); continue; @@ -304,7 +299,7 @@ class Cookie { * Handles parsing individual attributes from the cookie values. * * @param string $name Attribute name - * @param string|int|bool $value Attribute value (string/integer value, or true if empty/flag) + * @param string|boolean $value Attribute value (string value, or true if empty/flag) * @return mixed Value if available, or null if the attribute value is invalid (and should be skipped) */ protected function normalize_attribute($name, $value) { diff --git a/vendor/rmccue/requests/src/Cookie/Jar.php b/vendor/rmccue/requests/src/Cookie/Jar.php index 7633786b9..dfbb8b739 100644 --- a/vendor/rmccue/requests/src/Cookie/Jar.php +++ b/vendor/rmccue/requests/src/Cookie/Jar.php @@ -49,8 +49,7 @@ class Jar implements ArrayAccess, IteratorAggregate { /** * Normalise cookie data into a \WpOrg\Requests\Cookie * - * @param string|\WpOrg\Requests\Cookie $cookie Cookie header value, possibly pre-parsed (object). - * @param string $key Optional. The name for this cookie. + * @param string|\WpOrg\Requests\Cookie $cookie * @return \WpOrg\Requests\Cookie */ public function normalize_cookie($cookie, $key = '') { @@ -107,7 +106,7 @@ class Jar implements ArrayAccess, IteratorAggregate { /** * Unset the given header * - * @param string $offset The key for the item to unset. + * @param string $offset */ #[ReturnTypeWillChange] public function offsetUnset($offset) { @@ -172,7 +171,7 @@ class Jar implements ArrayAccess, IteratorAggregate { /** * Parse all cookies from a response and attach them to the response * - * @param \WpOrg\Requests\Response $response Response as received. + * @param \WpOrg\Requests\Response $response */ public function before_redirect_check(Response $response) { $url = $response->url; diff --git a/vendor/rmccue/requests/src/IdnaEncoder.php b/vendor/rmccue/requests/src/IdnaEncoder.php index 4257a1acb..094fff3d5 100644 --- a/vendor/rmccue/requests/src/IdnaEncoder.php +++ b/vendor/rmccue/requests/src/IdnaEncoder.php @@ -137,7 +137,7 @@ class IdnaEncoder { * * @internal (Testing found regex was the fastest implementation) * - * @param string $text Text to examine. + * @param string $text * @return bool Is the text string ASCII-only? */ protected static function is_ascii($text) { @@ -148,7 +148,7 @@ class IdnaEncoder { * Prepare a text string for use as an IDNA name * * @todo Implement this based on RFC 3491 and the newer 5891 - * @param string $text Text to prepare. + * @param string $text * @return string Prepared string */ protected static function nameprep($text) { @@ -160,7 +160,7 @@ class IdnaEncoder { * * Based on \WpOrg\Requests\Iri::replace_invalid_with_pct_encoding() * - * @param string $input Text to convert. + * @param string $input * @return array Unicode code points * * @throws \WpOrg\Requests\Exception Invalid UTF-8 codepoint (`idna.invalidcodepoint`) @@ -329,10 +329,10 @@ class IdnaEncoder { } // output the code point for digit t + ((q - t) mod (base - t)) - $digit = (int) ($t + (($q - $t) % (self::BOOTSTRAP_BASE - $t))); + $digit = $t + (($q - $t) % (self::BOOTSTRAP_BASE - $t)); $output .= self::digit_to_char($digit); // let q = (q - t) div (base - t) - $q = (int) floor(($q - $t) / (self::BOOTSTRAP_BASE - $t)); + $q = floor(($q - $t) / (self::BOOTSTRAP_BASE - $t)); } // end // output the code point for digit q $output .= self::digit_to_char($q); @@ -381,7 +381,7 @@ class IdnaEncoder { * @param int $delta * @param int $numpoints * @param bool $firsttime - * @return int|float New bias + * @return int New bias * * function adapt(delta,numpoints,firsttime): */ diff --git a/vendor/rmccue/requests/src/Iri.php b/vendor/rmccue/requests/src/Iri.php index c452c7365..244578d34 100644 --- a/vendor/rmccue/requests/src/Iri.php +++ b/vendor/rmccue/requests/src/Iri.php @@ -395,11 +395,11 @@ class Iri { // preceding "/" (if any) from the output buffer; otherwise, elseif (strpos($input, '/../') === 0) { $input = substr($input, 3); - $output = substr_replace($output, '', (strrpos($output, '/') ?: 0)); + $output = substr_replace($output, '', strrpos($output, '/')); } elseif ($input === '/..') { $input = '/'; - $output = substr_replace($output, '', (strrpos($output, '/') ?: 0)); + $output = substr_replace($output, '', strrpos($output, '/')); } // D: if the input buffer consists only of "." or "..", then remove // that from the input buffer; otherwise, @@ -824,8 +824,7 @@ class Iri { else { $iuserinfo = null; } - - if (($port_start = strpos($remaining, ':', (strpos($remaining, ']') ?: 0))) !== false) { + if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false) { $port = substr($remaining, $port_start + 1); if ($port === false || $port === '') { $port = null; diff --git a/vendor/rmccue/requests/src/Requests.php b/vendor/rmccue/requests/src/Requests.php index ac6ff55f9..a8d9d7e53 100644 --- a/vendor/rmccue/requests/src/Requests.php +++ b/vendor/rmccue/requests/src/Requests.php @@ -148,7 +148,7 @@ class Requests { * * @var string */ - const VERSION = '2.0.7'; + const VERSION = '2.0.5'; /** * Selected transport name @@ -642,14 +642,12 @@ class Requests { /** * Set the default values * - * The $options parameter is updated with the results. - * * @param string $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests * @param string $type HTTP request type * @param array $options Options for the request - * @return void + * @return void $options is updated with the results * * @throws \WpOrg\Requests\Exception When the $url is not an http(s) URL. */ @@ -826,11 +824,9 @@ class Requests { * Internal use only. Converts a raw HTTP response to a \WpOrg\Requests\Response * while still executing a multiple request. * - * `$response` is either set to a \WpOrg\Requests\Response instance, or a \WpOrg\Requests\Exception object - * * @param string $response Full response text including headers and body (will be overwritten with Response instance) * @param array $request Request data as passed into {@see \WpOrg\Requests\Requests::request_multiple()} - * @return void + * @return void `$response` is either set to a \WpOrg\Requests\Response instance, or a \WpOrg\Requests\Exception object */ public static function parse_multiple(&$response, $request) { try { diff --git a/vendor/rmccue/requests/src/Response.php b/vendor/rmccue/requests/src/Response.php index 86a0438ba..8964521a8 100644 --- a/vendor/rmccue/requests/src/Response.php +++ b/vendor/rmccue/requests/src/Response.php @@ -137,16 +137,16 @@ class Response { * * @link https://php.net/json-decode * - * @param bool|null $associative Optional. When `true`, JSON objects will be returned as associative arrays; - * When `false`, JSON objects will be returned as objects. - * When `null`, JSON objects will be returned as associative arrays - * or objects depending on whether `JSON_OBJECT_AS_ARRAY` is set in the flags. - * Defaults to `true` (in contrast to the PHP native default of `null`). - * @param int $depth Optional. Maximum nesting depth of the structure being decoded. - * Defaults to `512`. - * @param int $options Optional. Bitmask of JSON_BIGINT_AS_STRING, JSON_INVALID_UTF8_IGNORE, - * JSON_INVALID_UTF8_SUBSTITUTE, JSON_OBJECT_AS_ARRAY, JSON_THROW_ON_ERROR. - * Defaults to `0` (no options set). + * @param ?bool $associative Optional. When `true`, JSON objects will be returned as associative arrays; + * When `false`, JSON objects will be returned as objects. + * When `null`, JSON objects will be returned as associative arrays + * or objects depending on whether `JSON_OBJECT_AS_ARRAY` is set in the flags. + * Defaults to `true` (in contrast to the PHP native default of `null`). + * @param int $depth Optional. Maximum nesting depth of the structure being decoded. + * Defaults to `512`. + * @param int $options Optional. Bitmask of JSON_BIGINT_AS_STRING, JSON_INVALID_UTF8_IGNORE, + * JSON_INVALID_UTF8_SUBSTITUTE, JSON_OBJECT_AS_ARRAY, JSON_THROW_ON_ERROR. + * Defaults to `0` (no options set). * * @return array * diff --git a/vendor/rmccue/requests/src/Response/Headers.php b/vendor/rmccue/requests/src/Response/Headers.php index b4d0fcf91..eb4f68736 100644 --- a/vendor/rmccue/requests/src/Response/Headers.php +++ b/vendor/rmccue/requests/src/Response/Headers.php @@ -27,7 +27,7 @@ class Headers extends CaseInsensitiveDictionary { * Avoid using this where commas may be used unquoted in values, such as * Set-Cookie headers. * - * @param string $offset Name of the header to retrieve. + * @param string $offset * @return string|null Header value */ public function offsetGet($offset) { @@ -69,7 +69,7 @@ class Headers extends CaseInsensitiveDictionary { /** * Get all values for a given header * - * @param string $offset Name of the header to retrieve. + * @param string $offset * @return array|null Header values * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not valid as an array key. @@ -79,10 +79,7 @@ class Headers extends CaseInsensitiveDictionary { throw InvalidArgument::create(1, '$offset', 'string|int', gettype($offset)); } - if (is_string($offset)) { - $offset = strtolower($offset); - } - + $offset = strtolower($offset); if (!isset($this->data[$offset])) { return null; } diff --git a/vendor/rmccue/requests/src/Transport/Curl.php b/vendor/rmccue/requests/src/Transport/Curl.php index 7316987b5..8b0a13080 100644 --- a/vendor/rmccue/requests/src/Transport/Curl.php +++ b/vendor/rmccue/requests/src/Transport/Curl.php @@ -465,7 +465,7 @@ final class Curl implements Transport { * @param string $response Response data from the body * @param array $options Request options * @return string|false HTTP response data including headers. False if non-blocking. - * @throws \WpOrg\Requests\Exception If the request resulted in a cURL error. + * @throws \WpOrg\Requests\Exception */ public function process_response($response, $options) { if ($options['blocking'] === false) { @@ -561,7 +561,7 @@ final class Curl implements Transport { /** * Format a URL given GET data * - * @param string $url Original URL. + * @param string $url * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query} * @return string URL with data */ diff --git a/vendor/rmccue/requests/src/Transport/Fsockopen.php b/vendor/rmccue/requests/src/Transport/Fsockopen.php index 2b53d0c10..c3bd4a63d 100644 --- a/vendor/rmccue/requests/src/Transport/Fsockopen.php +++ b/vendor/rmccue/requests/src/Transport/Fsockopen.php @@ -51,11 +51,6 @@ final class Fsockopen implements Transport { */ private $max_bytes = false; - /** - * Cache for received connection errors. - * - * @var string - */ private $connect_error = ''; /** @@ -410,7 +405,7 @@ final class Fsockopen implements Transport { /** * Format a URL given GET data * - * @param array $url_parts Array of URL parts as received from {@link https://www.php.net/parse_url} + * @param array $url_parts * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query} * @return string URL with data */ diff --git a/vendor/rmccue/requests/src/Utility/CaseInsensitiveDictionary.php b/vendor/rmccue/requests/src/Utility/CaseInsensitiveDictionary.php index 0e1a914cd..3c24cebd4 100644 --- a/vendor/rmccue/requests/src/Utility/CaseInsensitiveDictionary.php +++ b/vendor/rmccue/requests/src/Utility/CaseInsensitiveDictionary.php @@ -95,7 +95,7 @@ class CaseInsensitiveDictionary implements ArrayAccess, IteratorAggregate { /** * Unset the given header * - * @param string $offset The key for the item to unset. + * @param string $offset */ #[ReturnTypeWillChange] public function offsetUnset($offset) { diff --git a/vendor/rmccue/requests/src/Utility/FilteredIterator.php b/vendor/rmccue/requests/src/Utility/FilteredIterator.php index 4865966c4..973a5d25a 100644 --- a/vendor/rmccue/requests/src/Utility/FilteredIterator.php +++ b/vendor/rmccue/requests/src/Utility/FilteredIterator.php @@ -28,7 +28,7 @@ final class FilteredIterator extends ArrayIterator { /** * Create a new iterator * - * @param array $data The array or object to be iterated on. + * @param array $data * @param callable $callback Callback to be called on each value * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data argument is not iterable. @@ -46,25 +46,14 @@ final class FilteredIterator extends ArrayIterator { } /** - * Prevent unserialization of the object for security reasons. + * @inheritdoc * * @phpcs:disable PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound - * - * @param array $data Restored array of data originally serialized. - * - * @return void */ #[ReturnTypeWillChange] public function __unserialize($data) {} // phpcs:enable - /** - * Perform reinitialization tasks. - * - * Prevents a callback from being injected during unserialization of an object. - * - * @return void - */ public function __wakeup() { unset($this->callback); } @@ -86,11 +75,7 @@ final class FilteredIterator extends ArrayIterator { } /** - * Prevent creating a PHP value from a stored representation of the object for security reasons. - * - * @param string $data The serialized string. - * - * @return void + * @inheritdoc */ #[ReturnTypeWillChange] public function unserialize($data) {} diff --git a/vendor/services.php b/vendor/services.php index ac7075047..11714ae7d 100755 --- a/vendor/services.php +++ b/vendor/services.php @@ -1,5 +1,5 @@ 'think\\app\\Service', diff --git a/vendor/symfony/deprecation-contracts/.gitignore b/vendor/symfony/deprecation-contracts/.gitignore new file mode 100644 index 000000000..c49a5d8df --- /dev/null +++ b/vendor/symfony/deprecation-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/vendor/symfony/deprecation-contracts/LICENSE b/vendor/symfony/deprecation-contracts/LICENSE index 0ed3a2465..406242ff2 100644 --- a/vendor/symfony/deprecation-contracts/LICENSE +++ b/vendor/symfony/deprecation-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-present Fabien Potencier +Copyright (c) 2020-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/deprecation-contracts/README.md b/vendor/symfony/deprecation-contracts/README.md index 9814864c0..4957933a6 100644 --- a/vendor/symfony/deprecation-contracts/README.md +++ b/vendor/symfony/deprecation-contracts/README.md @@ -22,5 +22,5 @@ trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use This will generate the following message: `Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.` -While not recommended, the deprecation notices can be completely ignored by declaring an empty +While not necessarily recommended, the deprecation notices can be completely ignored by declaring an empty `function trigger_deprecation() {}` in your application. diff --git a/vendor/symfony/deprecation-contracts/composer.json b/vendor/symfony/deprecation-contracts/composer.json index c6d02d874..1c1b4ba0e 100644 --- a/vendor/symfony/deprecation-contracts/composer.json +++ b/vendor/symfony/deprecation-contracts/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=8.1" + "php": ">=8.0.2" }, "autoload": { "files": [ @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/vendor/symfony/http-client-contracts/.gitignore b/vendor/symfony/http-client-contracts/.gitignore new file mode 100644 index 000000000..c49a5d8df --- /dev/null +++ b/vendor/symfony/http-client-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/vendor/symfony/http-client-contracts/HttpClientInterface.php b/vendor/symfony/http-client-contracts/HttpClientInterface.php index 59636258f..bc8d196f4 100644 --- a/vendor/symfony/http-client-contracts/HttpClientInterface.php +++ b/vendor/symfony/http-client-contracts/HttpClientInterface.php @@ -52,8 +52,8 @@ interface HttpClientInterface 'resolve' => [], // string[] - a map of host to IP address that SHOULD replace DNS resolution 'proxy' => null, // string - by default, the proxy-related env vars handled by curl SHOULD be honored 'no_proxy' => null, // string - a comma separated list of hosts that do not require a proxy to be reached - 'timeout' => null, // float - the idle timeout (in seconds) - defaults to ini_get('default_socket_timeout') - 'max_duration' => 0, // float - the maximum execution time (in seconds) for the request+response as a whole; + 'timeout' => null, // float - the idle timeout - defaults to ini_get('default_socket_timeout') + 'max_duration' => 0, // float - the maximum execution time for the request+response as a whole; // a value lower than or equal to 0 means it is unlimited 'bindto' => '0', // string - the interface or the local socket to bind to 'verify_peer' => true, // see https://php.net/context.ssl for the following options @@ -66,7 +66,6 @@ interface HttpClientInterface 'ciphers' => null, 'peer_fingerprint' => null, 'capture_peer_cert_chain' => false, - 'crypto_method' => \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, // STREAM_CRYPTO_METHOD_TLSv*_CLIENT - minimum TLS version 'extra' => [], // array - additional options that can be ignored if unsupported, unlike regular options ]; diff --git a/vendor/symfony/http-client-contracts/LICENSE b/vendor/symfony/http-client-contracts/LICENSE index 7536caeae..74cdc2dbf 100644 --- a/vendor/symfony/http-client-contracts/LICENSE +++ b/vendor/symfony/http-client-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2022 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/http-client-contracts/README.md b/vendor/symfony/http-client-contracts/README.md index 24d72f566..03b3a69b7 100644 --- a/vendor/symfony/http-client-contracts/README.md +++ b/vendor/symfony/http-client-contracts/README.md @@ -3,7 +3,7 @@ Symfony HttpClient Contracts A set of abstractions extracted out of the Symfony components. -Can be used to build on semantics that the Symfony components proved useful and +Can be used to build on semantics that the Symfony components proved useful - and that already have battle tested implementations. See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/vendor/symfony/http-client-contracts/Test/Fixtures/web/index.php b/vendor/symfony/http-client-contracts/Test/Fixtures/web/index.php index 8e28bf532..30a704975 100644 --- a/vendor/symfony/http-client-contracts/Test/Fixtures/web/index.php +++ b/vendor/symfony/http-client-contracts/Test/Fixtures/web/index.php @@ -15,7 +15,7 @@ if (!$_POST) { foreach ($_SERVER as $k => $v) { switch ($k) { default: - if (!str_starts_with($k, 'HTTP_')) { + if (0 !== strpos($k, 'HTTP_')) { continue 2; } // no break @@ -86,12 +86,6 @@ switch ($vars['REQUEST_URI']) { header('Location: //?foo=bar', true, 301); break; - case '/301/proxy': - case 'http://localhost:8057/301/proxy': - case 'http://127.0.0.1:8057/301/proxy': - header('Location: http://localhost:8057/', true, 301); - break; - case '/302': if (!isset($vars['HTTP_AUTHORIZATION'])) { header('Location: http://localhost:8057/', true, 302); diff --git a/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php b/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php index 9cfd33fc1..8cffeac71 100644 --- a/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php +++ b/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php @@ -226,13 +226,13 @@ abstract class HttpClientTestCase extends TestCase try { $response->getHeaders(); $this->fail(ClientExceptionInterface::class.' expected'); - } catch (ClientExceptionInterface) { + } catch (ClientExceptionInterface $e) { } try { $response->getContent(); $this->fail(ClientExceptionInterface::class.' expected'); - } catch (ClientExceptionInterface) { + } catch (ClientExceptionInterface $e) { } $this->assertSame(404, $response->getStatusCode()); @@ -246,7 +246,7 @@ abstract class HttpClientTestCase extends TestCase $this->assertTrue($chunk->isFirst()); } $this->fail(ClientExceptionInterface::class.' expected'); - } catch (ClientExceptionInterface) { + } catch (ClientExceptionInterface $e) { } } @@ -266,14 +266,14 @@ abstract class HttpClientTestCase extends TestCase try { $response->getStatusCode(); $this->fail(TransportExceptionInterface::class.' expected'); - } catch (TransportExceptionInterface) { + } catch (TransportExceptionInterface $e) { $this->addToAssertionCount(1); } try { $response->getStatusCode(); $this->fail(TransportExceptionInterface::class.' still expected'); - } catch (TransportExceptionInterface) { + } catch (TransportExceptionInterface $e) { $this->addToAssertionCount(1); } @@ -283,7 +283,7 @@ abstract class HttpClientTestCase extends TestCase foreach ($client->stream($response) as $r => $chunk) { } $this->fail(TransportExceptionInterface::class.' expected'); - } catch (TransportExceptionInterface) { + } catch (TransportExceptionInterface $e) { $this->addToAssertionCount(1); } @@ -437,7 +437,7 @@ abstract class HttpClientTestCase extends TestCase try { $response->getHeaders(); $this->fail(RedirectionExceptionInterface::class.' expected'); - } catch (RedirectionExceptionInterface) { + } catch (RedirectionExceptionInterface $e) { } $this->assertSame(302, $response->getStatusCode()); @@ -859,7 +859,7 @@ abstract class HttpClientTestCase extends TestCase try { $response->getContent(); $this->fail(TransportExceptionInterface::class.' expected'); - } catch (TransportExceptionInterface) { + } catch (TransportExceptionInterface $e) { } } $responses = []; @@ -892,7 +892,7 @@ abstract class HttpClientTestCase extends TestCase try { unset($response); $this->fail(TransportExceptionInterface::class.' expected'); - } catch (TransportExceptionInterface) { + } catch (TransportExceptionInterface $e) { } } @@ -969,14 +969,6 @@ abstract class HttpClientTestCase extends TestCase } finally { unset($_SERVER['http_proxy']); } - - $response = $client->request('GET', 'http://localhost:8057/301/proxy', [ - 'proxy' => 'http://localhost:8057', - ]); - - $body = $response->toArray(); - $this->assertSame('localhost:8057', $body['HTTP_HOST']); - $this->assertMatchesRegularExpression('#^http://(localhost|127\.0\.0\.1):8057/$#', $body['REQUEST_URI']); } public function testNoProxy() @@ -1118,7 +1110,7 @@ abstract class HttpClientTestCase extends TestCase try { $response->getContent(); - } catch (TransportExceptionInterface) { + } catch (TransportExceptionInterface $e) { $this->addToAssertionCount(1); } @@ -1133,7 +1125,7 @@ abstract class HttpClientTestCase extends TestCase $client2 = $client->withOptions(['base_uri' => 'http://localhost:8057/']); $this->assertNotSame($client, $client2); - $this->assertSame($client::class, $client2::class); + $this->assertSame(\get_class($client), \get_class($client2)); $response = $client2->request('GET', '/'); $this->assertSame(200, $response->getStatusCode()); diff --git a/vendor/symfony/http-client-contracts/composer.json b/vendor/symfony/http-client-contracts/composer.json index 084d49072..a26300f4a 100644 --- a/vendor/symfony/http-client-contracts/composer.json +++ b/vendor/symfony/http-client-contracts/composer.json @@ -16,18 +16,18 @@ } ], "require": { - "php": ">=8.1" + "php": ">=8.0.2" + }, + "suggest": { + "symfony/http-client-implementation": "" }, "autoload": { - "psr-4": { "Symfony\\Contracts\\HttpClient\\": "" }, - "exclude-from-classmap": [ - "/Test/" - ] + "psr-4": { "Symfony\\Contracts\\HttpClient\\": "" } }, "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.0-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/vendor/symfony/http-client/AmpHttpClient.php b/vendor/symfony/http-client/AmpHttpClient.php index a8d731150..cddd3cd3a 100644 --- a/vendor/symfony/http-client/AmpHttpClient.php +++ b/vendor/symfony/http-client/AmpHttpClient.php @@ -49,20 +49,21 @@ final class AmpHttpClient implements HttpClientInterface, LoggerAwareInterface, private array $defaultOptions = self::OPTIONS_DEFAULTS; private static array $emptyDefaults = self::OPTIONS_DEFAULTS; - private AmpClientState $multi; + + private $multi; /** - * @param array $defaultOptions Default requests' options - * @param callable|null $clientConfigurator A callable that builds a {@see DelegateHttpClient} from a {@see PooledHttpClient}; - * passing null builds an {@see InterceptedHttpClient} with 2 retries on failures - * @param int $maxHostConnections The maximum number of connections to a single host - * @param int $maxPendingPushes The maximum number of pushed responses to accept in the queue + * @param array $defaultOptions Default requests' options + * @param callable $clientConfigurator A callable that builds a {@see DelegateHttpClient} from a {@see PooledHttpClient}; + * passing null builds an {@see InterceptedHttpClient} with 2 retries on failures + * @param int $maxHostConnections The maximum number of connections to a single host + * @param int $maxPendingPushes The maximum number of pushed responses to accept in the queue * * @see HttpClientInterface::OPTIONS_DEFAULTS for available options */ public function __construct(array $defaultOptions = [], callable $clientConfigurator = null, int $maxHostConnections = 6, int $maxPendingPushes = 50) { - $this->defaultOptions['buffer'] ??= self::shouldBuffer(...); + $this->defaultOptions['buffer'] = $this->defaultOptions['buffer'] ?? \Closure::fromCallable([__CLASS__, 'shouldBuffer']); if ($defaultOptions) { [, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions); @@ -73,6 +74,8 @@ final class AmpHttpClient implements HttpClientInterface, LoggerAwareInterface, /** * @see HttpClientInterface::OPTIONS_DEFAULTS for available options + * + * {@inheritdoc} */ public function request(string $method, string $url, array $options = []): ResponseInterface { @@ -85,10 +88,10 @@ final class AmpHttpClient implements HttpClientInterface, LoggerAwareInterface, } if ($options['bindto']) { - if (str_starts_with($options['bindto'], 'if!')) { + if (0 === strpos($options['bindto'], 'if!')) { throw new TransportException(__CLASS__.' cannot bind to network interfaces, use e.g. CurlHttpClient instead.'); } - if (str_starts_with($options['bindto'], 'host!')) { + if (0 === strpos($options['bindto'], 'host!')) { $options['bindto'] = substr($options['bindto'], 5); } } @@ -116,11 +119,11 @@ final class AmpHttpClient implements HttpClientInterface, LoggerAwareInterface, $request = new Request(implode('', $url), $method); if ($options['http_version']) { - $request->setProtocolVersions(match ((float) $options['http_version']) { - 1.0 => ['1.0'], - 1.1 => $request->setProtocolVersions(['1.1', '1.0']), - default => ['2', '1.1', '1.0'], - }); + switch ((float) $options['http_version']) { + case 1.0: $request->setProtocolVersions(['1.0']); break; + case 1.1: $request->setProtocolVersions(['1.1', '1.0']); break; + default: $request->setProtocolVersions(['2', '1.1', '1.0']); break; + } } foreach ($options['headers'] as $v) { @@ -144,6 +147,9 @@ final class AmpHttpClient implements HttpClientInterface, LoggerAwareInterface, return new AmpResponse($this->multi, $request, $options, $this->logger); } + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { if ($responses instanceof AmpResponse) { @@ -161,7 +167,9 @@ final class AmpHttpClient implements HttpClientInterface, LoggerAwareInterface, foreach ($pushedResponses as [$pushedUrl, $pushDeferred]) { $pushDeferred->fail(new CancelledException()); - $this->logger?->debug(sprintf('Unused pushed response: "%s"', $pushedUrl)); + if ($this->logger) { + $this->logger->debug(sprintf('Unused pushed response: "%s"', $pushedUrl)); + } } } diff --git a/vendor/symfony/http-client/AsyncDecoratorTrait.php b/vendor/symfony/http-client/AsyncDecoratorTrait.php index 912b8250e..1a2aa4fb0 100644 --- a/vendor/symfony/http-client/AsyncDecoratorTrait.php +++ b/vendor/symfony/http-client/AsyncDecoratorTrait.php @@ -26,10 +26,15 @@ trait AsyncDecoratorTrait use DecoratorTrait; /** + * {@inheritdoc} + * * @return AsyncResponse */ abstract public function request(string $method, string $url, array $options = []): ResponseInterface; + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { if ($responses instanceof AsyncResponse) { diff --git a/vendor/symfony/http-client/CHANGELOG.md b/vendor/symfony/http-client/CHANGELOG.md index d6d50d2d5..7c2fc2273 100644 --- a/vendor/symfony/http-client/CHANGELOG.md +++ b/vendor/symfony/http-client/CHANGELOG.md @@ -1,19 +1,6 @@ CHANGELOG ========= -6.2 ---- - - * Make `HttplugClient` implement `Psr\Http\Message\RequestFactoryInterface`, `StreamFactoryInterface` and `UriFactoryInterface` - * Deprecate implementing `Http\Message\RequestFactory`, `StreamFactory` and `UriFactory` on `HttplugClient` - * Add `withOptions()` to `HttplugClient` and `Psr18Client` - -6.1 ---- - - * Allow yielding `Exception` from MockResponse's `$body` to mock transport errors - * Remove credentials from requests redirected to same host but different port - 5.4 --- diff --git a/vendor/symfony/http-client/CachingHttpClient.php b/vendor/symfony/http-client/CachingHttpClient.php index 5e3fbf507..0271fda64 100644 --- a/vendor/symfony/http-client/CachingHttpClient.php +++ b/vendor/symfony/http-client/CachingHttpClient.php @@ -35,8 +35,8 @@ class CachingHttpClient implements HttpClientInterface, ResetInterface { use HttpClientTrait; - private HttpClientInterface $client; - private HttpCache $cache; + private $client; + private $cache; private array $defaultOptions = self::OPTIONS_DEFAULTS; public function __construct(HttpClientInterface $client, StoreInterface $store, array $defaultOptions = []) @@ -64,6 +64,9 @@ class CachingHttpClient implements HttpClientInterface, ResetInterface } } + /** + * {@inheritdoc} + */ public function request(string $method, string $url, array $options = []): ResponseInterface { [$url, $options] = $this->prepareRequest($method, $url, $options, $this->defaultOptions, true); @@ -104,6 +107,9 @@ class CachingHttpClient implements HttpClientInterface, ResetInterface return MockResponse::fromRequest($method, $url, $options, $response); } + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { if ($responses instanceof ResponseInterface) { diff --git a/vendor/symfony/http-client/Chunk/DataChunk.php b/vendor/symfony/http-client/Chunk/DataChunk.php index 3507a0cd0..e2365cd0b 100644 --- a/vendor/symfony/http-client/Chunk/DataChunk.php +++ b/vendor/symfony/http-client/Chunk/DataChunk.php @@ -29,36 +29,57 @@ class DataChunk implements ChunkInterface $this->content = $content; } + /** + * {@inheritdoc} + */ public function isTimeout(): bool { return false; } + /** + * {@inheritdoc} + */ public function isFirst(): bool { return false; } + /** + * {@inheritdoc} + */ public function isLast(): bool { return false; } + /** + * {@inheritdoc} + */ public function getInformationalStatus(): ?array { return null; } + /** + * {@inheritdoc} + */ public function getContent(): string { return $this->content; } + /** + * {@inheritdoc} + */ public function getOffset(): int { return $this->offset; } + /** + * {@inheritdoc} + */ public function getError(): ?string { return null; diff --git a/vendor/symfony/http-client/Chunk/ErrorChunk.php b/vendor/symfony/http-client/Chunk/ErrorChunk.php index c797fc343..a989c39a7 100644 --- a/vendor/symfony/http-client/Chunk/ErrorChunk.php +++ b/vendor/symfony/http-client/Chunk/ErrorChunk.php @@ -39,6 +39,9 @@ class ErrorChunk implements ChunkInterface } } + /** + * {@inheritdoc} + */ public function isTimeout(): bool { $this->didThrow = true; @@ -50,35 +53,53 @@ class ErrorChunk implements ChunkInterface return true; } + /** + * {@inheritdoc} + */ public function isFirst(): bool { $this->didThrow = true; throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage); } + /** + * {@inheritdoc} + */ public function isLast(): bool { $this->didThrow = true; throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage); } + /** + * {@inheritdoc} + */ public function getInformationalStatus(): ?array { $this->didThrow = true; throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage); } + /** + * {@inheritdoc} + */ public function getContent(): string { $this->didThrow = true; throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage); } + /** + * {@inheritdoc} + */ public function getOffset(): int { return $this->offset; } + /** + * {@inheritdoc} + */ public function getError(): ?string { return $this->errorMessage; diff --git a/vendor/symfony/http-client/Chunk/FirstChunk.php b/vendor/symfony/http-client/Chunk/FirstChunk.php index f6ba8b8ac..d891ca856 100644 --- a/vendor/symfony/http-client/Chunk/FirstChunk.php +++ b/vendor/symfony/http-client/Chunk/FirstChunk.php @@ -18,6 +18,9 @@ namespace Symfony\Component\HttpClient\Chunk; */ class FirstChunk extends DataChunk { + /** + * {@inheritdoc} + */ public function isFirst(): bool { return true; diff --git a/vendor/symfony/http-client/Chunk/InformationalChunk.php b/vendor/symfony/http-client/Chunk/InformationalChunk.php index 31ed1aa24..fbc3ccbd1 100644 --- a/vendor/symfony/http-client/Chunk/InformationalChunk.php +++ b/vendor/symfony/http-client/Chunk/InformationalChunk.php @@ -25,6 +25,9 @@ class InformationalChunk extends DataChunk $this->status = [$statusCode, $headers]; } + /** + * {@inheritdoc} + */ public function getInformationalStatus(): ?array { return $this->status; diff --git a/vendor/symfony/http-client/Chunk/LastChunk.php b/vendor/symfony/http-client/Chunk/LastChunk.php index a64d12379..84095d392 100644 --- a/vendor/symfony/http-client/Chunk/LastChunk.php +++ b/vendor/symfony/http-client/Chunk/LastChunk.php @@ -18,6 +18,9 @@ namespace Symfony\Component\HttpClient\Chunk; */ class LastChunk extends DataChunk { + /** + * {@inheritdoc} + */ public function isLast(): bool { return true; diff --git a/vendor/symfony/http-client/Chunk/ServerSentEvent.php b/vendor/symfony/http-client/Chunk/ServerSentEvent.php index 296918e6a..1f55ba4d7 100644 --- a/vendor/symfony/http-client/Chunk/ServerSentEvent.php +++ b/vendor/symfony/http-client/Chunk/ServerSentEvent.php @@ -29,7 +29,7 @@ final class ServerSentEvent extends DataChunk implements ChunkInterface parent::__construct(-1, $content); // remove BOM - if (str_starts_with($content, "\xEF\xBB\xBF")) { + if (0 === strpos($content, "\xEF\xBB\xBF")) { $content = substr($content, 3); } diff --git a/vendor/symfony/http-client/CurlHttpClient.php b/vendor/symfony/http-client/CurlHttpClient.php index 3143599e9..4bc8f9151 100644 --- a/vendor/symfony/http-client/CurlHttpClient.php +++ b/vendor/symfony/http-client/CurlHttpClient.php @@ -50,7 +50,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, /** * An internal object to share state between the client and its responses. */ - private CurlClientState $multi; + private $multi; /** * @param array $defaultOptions Default request's options @@ -65,7 +65,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\CurlHttpClient" as the "curl" extension is not installed.'); } - $this->defaultOptions['buffer'] ??= self::shouldBuffer(...); + $this->defaultOptions['buffer'] = $this->defaultOptions['buffer'] ?? \Closure::fromCallable([__CLASS__, 'shouldBuffer']); if ($defaultOptions) { [, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions); @@ -81,6 +81,8 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, /** * @see HttpClientInterface::OPTIONS_DEFAULTS for available options + * + * {@inheritdoc} */ public function request(string $method, string $url, array $options = []): ResponseInterface { @@ -88,8 +90,10 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, $scheme = $url['scheme']; $authority = $url['authority']; $host = parse_url($authority, \PHP_URL_HOST); - $port = parse_url($authority, \PHP_URL_PORT) ?: ('http:' === $scheme ? 80 : 443); - $proxy = self::getProxyUrl($options['proxy'], $url); + $proxy = $options['proxy'] + ?? ('https:' === $url['scheme'] ? $_SERVER['https_proxy'] ?? $_SERVER['HTTPS_PROXY'] ?? null : null) + // Ignore HTTP_PROXY except on the CLI to work around httpoxy set of vulnerabilities + ?? $_SERVER['http_proxy'] ?? (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? $_SERVER['HTTP_PROXY'] ?? null : null) ?? $_SERVER['all_proxy'] ?? $_SERVER['ALL_PROXY'] ?? null; $url = implode('', $url); if (!isset($options['normalized_headers']['user-agent'])) { @@ -163,6 +167,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, // First reset any old DNS cache entries then add the new ones $resolve = $this->multi->dnsCache->evictions; $this->multi->dnsCache->evictions = []; + $port = parse_url($authority, \PHP_URL_PORT) ?: ('http:' === $scheme ? 80 : 443); if ($resolve && 0x072A00 > CurlClientState::$curlVersion['version_number']) { // DNS cache removals require curl 7.42 or higher @@ -278,21 +283,21 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, unset($this->multi->pushedResponses[$url]); if (self::acceptPushForRequest($method, $options, $pushedResponse)) { - $this->logger?->debug(sprintf('Accepting pushed response: "%s %s"', $method, $url)); + $this->logger && $this->logger->debug(sprintf('Accepting pushed response: "%s %s"', $method, $url)); // Reinitialize the pushed response with request's options $ch = $pushedResponse->handle; $pushedResponse = $pushedResponse->response; $pushedResponse->__construct($this->multi, $url, $options, $this->logger); } else { - $this->logger?->debug(sprintf('Rejecting pushed response: "%s"', $url)); + $this->logger && $this->logger->debug(sprintf('Rejecting pushed response: "%s"', $url)); $pushedResponse = null; } } if (!$pushedResponse) { $ch = curl_init(); - $this->logger?->info(sprintf('Request: "%s %s"', $method, $url)); + $this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, $url)); $curlopts += [\CURLOPT_SHARE => $this->multi->share]; } @@ -303,9 +308,12 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, } } - return $pushedResponse ?? new CurlResponse($this->multi, $ch, $options, $this->logger, $method, self::createRedirectResolver($options, $host, $port), CurlClientState::$curlVersion['version_number'], $url); + return $pushedResponse ?? new CurlResponse($this->multi, $ch, $options, $this->logger, $method, self::createRedirectResolver($options, $host), CurlClientState::$curlVersion['version_number']); } + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { if ($responses instanceof CurlResponse) { @@ -380,12 +388,11 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, * * Work around CVE-2018-1000007: Authorization and Cookie headers should not follow redirects - fixed in Curl 7.64 */ - private static function createRedirectResolver(array $options, string $host, int $port): \Closure + private static function createRedirectResolver(array $options, string $host): \Closure { $redirectHeaders = []; if (0 < $options['max_redirects']) { $redirectHeaders['host'] = $host; - $redirectHeaders['port'] = $port; $redirectHeaders['with_auth'] = $redirectHeaders['no_auth'] = array_filter($options['headers'], static function ($h) { return 0 !== stripos($h, 'Host:'); }); @@ -397,10 +404,10 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, } } - return static function ($ch, string $location, bool $noContent) use (&$redirectHeaders, $options) { + return static function ($ch, string $location, bool $noContent) use (&$redirectHeaders) { try { $location = self::parseUrl($location); - } catch (InvalidArgumentException) { + } catch (InvalidArgumentException $e) { return null; } @@ -413,8 +420,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, } if ($redirectHeaders && $host = parse_url('http:'.$location['authority'], \PHP_URL_HOST)) { - $port = parse_url('http:'.$location['authority'], \PHP_URL_PORT) ?: ('http:' === $location['scheme'] ? 80 : 443); - $requestHeaders = $redirectHeaders['host'] === $host && $redirectHeaders['port'] === $port ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth']; + $requestHeaders = $redirectHeaders['host'] === $host ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth']; curl_setopt($ch, \CURLOPT_HTTPHEADER, $requestHeaders); } elseif ($noContent && $redirectHeaders) { curl_setopt($ch, \CURLOPT_HTTPHEADER, $redirectHeaders['with_auth']); @@ -423,7 +429,11 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, $url = self::parseUrl(curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL)); $url = self::resolveUrl($location, $url); - curl_setopt($ch, \CURLOPT_PROXY, self::getProxyUrl($options['proxy'], $url)); + curl_setopt($ch, \CURLOPT_PROXY, $options['proxy'] + ?? ('https:' === $url['scheme'] ? $_SERVER['https_proxy'] ?? $_SERVER['HTTPS_PROXY'] ?? null : null) + // Ignore HTTP_PROXY except on the CLI to work around httpoxy set of vulnerabilities + ?? $_SERVER['http_proxy'] ?? (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? $_SERVER['HTTP_PROXY'] ?? null : null) ?? $_SERVER['all_proxy'] ?? $_SERVER['ALL_PROXY'] ?? null + ); return implode('', $url); }; @@ -459,7 +469,6 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, \CURLOPT_TIMEOUT_MS => 'max_duration', \CURLOPT_TIMEOUT => 'max_duration', \CURLOPT_MAXREDIRS => 'max_redirects', - \CURLOPT_POSTREDIR => 'max_redirects', \CURLOPT_PROXY => 'proxy', \CURLOPT_NOPROXY => 'no_proxy', \CURLOPT_SSL_VERIFYPEER => 'verify_peer', diff --git a/vendor/symfony/http-client/DataCollector/HttpClientDataCollector.php b/vendor/symfony/http-client/DataCollector/HttpClientDataCollector.php index 524251729..dda03d5a3 100644 --- a/vendor/symfony/http-client/DataCollector/HttpClientDataCollector.php +++ b/vendor/symfony/http-client/DataCollector/HttpClientDataCollector.php @@ -11,7 +11,6 @@ namespace Symfony\Component\HttpClient\DataCollector; -use Symfony\Component\HttpClient\HttpClientTrait; use Symfony\Component\HttpClient\TraceableHttpClient; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -24,8 +23,6 @@ use Symfony\Component\VarDumper\Caster\ImgStub; */ final class HttpClientDataCollector extends DataCollector implements LateDataCollectorInterface { - use HttpClientTrait; - /** * @var TraceableHttpClient[] */ @@ -36,6 +33,9 @@ final class HttpClientDataCollector extends DataCollector implements LateDataCol $this->clients[$name] = $client; } + /** + * {@inheritdoc} + */ public function collect(Request $request, Response $response, \Throwable $exception = null) { $this->lateCollect(); @@ -43,8 +43,8 @@ final class HttpClientDataCollector extends DataCollector implements LateDataCol public function lateCollect() { - $this->data['request_count'] = $this->data['request_count'] ?? 0; - $this->data['error_count'] = $this->data['error_count'] ?? 0; + $this->data['request_count'] = 0; + $this->data['error_count'] = 0; $this->data += ['clients' => []]; foreach ($this->clients as $name => $client) { @@ -59,8 +59,7 @@ final class HttpClientDataCollector extends DataCollector implements LateDataCol $this->data['clients'][$name]['traces'] = array_merge($this->data['clients'][$name]['traces'], $traces); $this->data['request_count'] += \count($traces); - $this->data['error_count'] += $errorCount; - $this->data['clients'][$name]['error_count'] += $errorCount; + $this->data['error_count'] += $this->data['clients'][$name]['error_count'] += $errorCount; $client->reset(); } @@ -81,6 +80,9 @@ final class HttpClientDataCollector extends DataCollector implements LateDataCol return $this->data['error_count'] ?? 0; } + /** + * {@inheritdoc} + */ public function getName(): string { return 'http_client'; @@ -143,7 +145,7 @@ final class HttpClientDataCollector extends DataCollector implements LateDataCol } } - if (str_starts_with($contentType, 'image/') && class_exists(ImgStub::class)) { + if (0 === strpos($contentType, 'image/') && class_exists(ImgStub::class)) { $content = new ImgStub($content, $contentType, ''); } else { $content = [$content]; @@ -166,97 +168,8 @@ final class HttpClientDataCollector extends DataCollector implements LateDataCol unset($traces[$i]['info']); // break PHP reference used by TraceableHttpClient $traces[$i]['info'] = $this->cloneVar($info); $traces[$i]['options'] = $this->cloneVar($trace['options']); - $traces[$i]['curlCommand'] = $this->getCurlCommand($trace); } return [$errorCount, $traces]; } - - private function getCurlCommand(array $trace): ?string - { - if (!isset($trace['info']['debug'])) { - return null; - } - - $url = $trace['info']['original_url'] ?? $trace['info']['url'] ?? $trace['url']; - $command = ['curl', '--compressed']; - - if (isset($trace['options']['resolve'])) { - $port = parse_url($url, \PHP_URL_PORT) ?: (str_starts_with('http:', $url) ? 80 : 443); - foreach ($trace['options']['resolve'] as $host => $ip) { - if (null !== $ip) { - $command[] = '--resolve '.escapeshellarg("$host:$port:$ip"); - } - } - } - - $dataArg = []; - - if ($json = $trace['options']['json'] ?? null) { - if (!$this->argMaxLengthIsSafe($payload = self::jsonEncode($json))) { - return null; - } - $dataArg[] = '--data '.escapeshellarg($payload); - } elseif ($body = $trace['options']['body'] ?? null) { - if (\is_string($body)) { - if (!$this->argMaxLengthIsSafe($body)) { - return null; - } - try { - $dataArg[] = '--data '.escapeshellarg($body); - } catch (\ValueError) { - return null; - } - } elseif (\is_array($body)) { - $body = explode('&', self::normalizeBody($body)); - foreach ($body as $value) { - if (!$this->argMaxLengthIsSafe($payload = urldecode($value))) { - return null; - } - $dataArg[] = '--data '.escapeshellarg($payload); - } - } else { - return null; - } - } - - $dataArg = empty($dataArg) ? null : implode(' ', $dataArg); - - foreach (explode("\n", $trace['info']['debug']) as $line) { - $line = substr($line, 0, -1); - - if (str_starts_with('< ', $line)) { - // End of the request, beginning of the response. Stop parsing. - break; - } - - if ('' === $line || preg_match('/^[*<]|(Host: )/', $line)) { - continue; - } - - if (preg_match('/^> ([A-Z]+)/', $line, $match)) { - $command[] = sprintf('--request %s', $match[1]); - $command[] = sprintf('--url %s', escapeshellarg($url)); - continue; - } - - $command[] = '--header '.escapeshellarg($line); - } - - if (null !== $dataArg) { - $command[] = $dataArg; - } - - return implode(" \\\n ", $command); - } - - /** - * Let's be defensive : we authorize only size of 8kio on Windows for escapeshellarg() argument to avoid a fatal error. - * - * @see https://github.com/php/php-src/blob/9458f5f2c8a8e3d6c65cc181747a5a75654b7c6e/ext/standard/exec.c#L397 - */ - private function argMaxLengthIsSafe(string $payload): bool - { - return \strlen($payload) < ('\\' === \DIRECTORY_SEPARATOR ? 8100 : 256000); - } } diff --git a/vendor/symfony/http-client/DecoratorTrait.php b/vendor/symfony/http-client/DecoratorTrait.php index f38664b43..a08b725c9 100644 --- a/vendor/symfony/http-client/DecoratorTrait.php +++ b/vendor/symfony/http-client/DecoratorTrait.php @@ -23,23 +23,32 @@ use Symfony\Contracts\Service\ResetInterface; */ trait DecoratorTrait { - private HttpClientInterface $client; + private $client; public function __construct(HttpClientInterface $client = null) { $this->client = $client ?? HttpClient::create(); } + /** + * {@inheritdoc} + */ public function request(string $method, string $url, array $options = []): ResponseInterface { return $this->client->request($method, $url, $options); } + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { return $this->client->stream($responses, $timeout); } + /** + * {@inheritdoc} + */ public function withOptions(array $options): static { $clone = clone $this; diff --git a/vendor/symfony/http-client/DependencyInjection/HttpClientPass.php b/vendor/symfony/http-client/DependencyInjection/HttpClientPass.php index c42d873fc..53645a12f 100644 --- a/vendor/symfony/http-client/DependencyInjection/HttpClientPass.php +++ b/vendor/symfony/http-client/DependencyInjection/HttpClientPass.php @@ -19,6 +19,9 @@ use Symfony\Component\HttpClient\TraceableHttpClient; final class HttpClientPass implements CompilerPassInterface { + /** + * {@inheritdoc} + */ public function process(ContainerBuilder $container) { if (!$container->hasDefinition('data_collector.http_client')) { diff --git a/vendor/symfony/http-client/EventSourceHttpClient.php b/vendor/symfony/http-client/EventSourceHttpClient.php index 377c29d5f..11c54848e 100644 --- a/vendor/symfony/http-client/EventSourceHttpClient.php +++ b/vendor/symfony/http-client/EventSourceHttpClient.php @@ -84,7 +84,7 @@ final class EventSourceHttpClient implements HttpClientInterface, ResetInterface return; } - } catch (TransportExceptionInterface) { + } catch (TransportExceptionInterface $e) { $state->lastError = $lastError ?? microtime(true); if (null === $state->buffer || ($isTimeout && microtime(true) - $state->lastError < $state->reconnectionTime)) { diff --git a/vendor/symfony/http-client/Exception/HttpExceptionTrait.php b/vendor/symfony/http-client/Exception/HttpExceptionTrait.php index 264ef24b2..8cbaa1cd1 100644 --- a/vendor/symfony/http-client/Exception/HttpExceptionTrait.php +++ b/vendor/symfony/http-client/Exception/HttpExceptionTrait.php @@ -20,7 +20,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface; */ trait HttpExceptionTrait { - private ResponseInterface $response; + private $response; public function __construct(ResponseInterface $response) { diff --git a/vendor/symfony/http-client/HttpClient.php b/vendor/symfony/http-client/HttpClient.php index 0e7d9b440..352410d33 100644 --- a/vendor/symfony/http-client/HttpClient.php +++ b/vendor/symfony/http-client/HttpClient.php @@ -42,7 +42,7 @@ final class HttpClient } static $curlVersion = null; - $curlVersion ??= curl_version(); + $curlVersion = $curlVersion ?? curl_version(); // HTTP/2 push crashes before curl 7.61 if (0x073D00 > $curlVersion['version_number'] || !(\CURL_VERSION_HTTP2 & $curlVersion['features'])) { diff --git a/vendor/symfony/http-client/HttpClientTrait.php b/vendor/symfony/http-client/HttpClientTrait.php index 36118113f..f09b4e8ea 100644 --- a/vendor/symfony/http-client/HttpClientTrait.php +++ b/vendor/symfony/http-client/HttpClientTrait.php @@ -25,6 +25,9 @@ trait HttpClientTrait { private static int $CHUNK_SIZE = 16372; + /** + * {@inheritdoc} + */ public function withOptions(array $options): static { $clone = clone $this; @@ -94,10 +97,6 @@ trait HttpClientTrait } if (isset($options['body'])) { - if (\is_array($options['body']) && (!isset($options['normalized_headers']['content-type'][0]) || !str_contains($options['normalized_headers']['content-type'][0], 'application/x-www-form-urlencoded'))) { - $options['normalized_headers']['content-type'] = ['Content-Type: application/x-www-form-urlencoded']; - } - $options['body'] = self::normalizeBody($options['body']); if (\is_string($options['body']) @@ -203,7 +202,7 @@ trait HttpClientTrait } // Option "query" is never inherited from defaults - $options['query'] ??= []; + $options['query'] = $options['query'] ?? []; $options += $defaultOptions; @@ -395,13 +394,13 @@ trait HttpClientTrait private static function normalizePeerFingerprint(mixed $fingerprint): array { if (\is_string($fingerprint)) { - $fingerprint = match (\strlen($fingerprint = str_replace(':', '', $fingerprint))) { - 32 => ['md5' => $fingerprint], - 40 => ['sha1' => $fingerprint], - 44 => ['pin-sha256' => [$fingerprint]], - 64 => ['sha256' => $fingerprint], - default => throw new InvalidArgumentException(sprintf('Cannot auto-detect fingerprint algorithm for "%s".', $fingerprint)), - }; + switch (\strlen($fingerprint = str_replace(':', '', $fingerprint))) { + case 32: $fingerprint = ['md5' => $fingerprint]; break; + case 40: $fingerprint = ['sha1' => $fingerprint]; break; + case 44: $fingerprint = ['pin-sha256' => [$fingerprint]]; break; + case 64: $fingerprint = ['sha256' => $fingerprint]; break; + default: throw new InvalidArgumentException(sprintf('Cannot auto-detect fingerprint algorithm for "%s".', $fingerprint)); + } } elseif (\is_array($fingerprint)) { foreach ($fingerprint as $algo => $hash) { $fingerprint[$algo] = 'pin-sha256' === $algo ? (array) $hash : str_replace(':', '', $hash); @@ -418,7 +417,7 @@ trait HttpClientTrait */ private static function jsonEncode(mixed $value, int $flags = null, int $maxDepth = 512): string { - $flags ??= \JSON_HEX_TAG | \JSON_HEX_APOS | \JSON_HEX_AMP | \JSON_HEX_QUOT | \JSON_PRESERVE_ZERO_FRACTION; + $flags = $flags ?? (\JSON_HEX_TAG | \JSON_HEX_APOS | \JSON_HEX_AMP | \JSON_HEX_QUOT | \JSON_PRESERVE_ZERO_FRACTION); try { $value = json_encode($value, $flags | \JSON_THROW_ON_ERROR, $maxDepth); @@ -458,7 +457,7 @@ trait HttpClientTrait } else { if (null === $url['path']) { $url['path'] = $base['path']; - $url['query'] ??= $base['query']; + $url['query'] = $url['query'] ?? $base['query']; } else { if ('/' !== $url['path'][0]) { if (null === $base['path']) { @@ -540,7 +539,7 @@ trait HttpClientTrait } // https://tools.ietf.org/html/rfc3986#section-3.3 - $parts[$part] = preg_replace_callback("#[^-A-Za-z0-9._~!$&/'()[\]*+,;=:@{}%]++#", function ($m) { return rawurlencode($m[0]); }, $parts[$part]); + $parts[$part] = preg_replace_callback("#[^-A-Za-z0-9._~!$&/'()*+,;=:@%]++#", function ($m) { return rawurlencode($m[0]); }, $parts[$part]); } return [ @@ -614,23 +613,6 @@ trait HttpClientTrait $queryArray = []; if ($queryString) { - if (str_contains($queryString, '%')) { - // https://tools.ietf.org/html/rfc3986#section-2.3 + some chars not encoded by browsers - $queryString = strtr($queryString, [ - '%21' => '!', - '%24' => '$', - '%28' => '(', - '%29' => ')', - '%2A' => '*', - '%2F' => '/', - '%3A' => ':', - '%3B' => ';', - '%40' => '@', - '%5B' => '[', - '%5D' => ']', - ]); - } - foreach (explode('&', $queryString) as $v) { $queryArray[rawurldecode(explode('=', $v, 2)[0])] = $v; } @@ -644,7 +626,16 @@ trait HttpClientTrait */ private static function getProxy(?string $proxy, array $url, ?string $noProxy): ?array { - if (null === $proxy = self::getProxyUrl($proxy, $url)) { + if (null === $proxy) { + // Ignore HTTP_PROXY except on the CLI to work around httpoxy set of vulnerabilities + $proxy = $_SERVER['http_proxy'] ?? (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? $_SERVER['HTTP_PROXY'] ?? null : null) ?? $_SERVER['all_proxy'] ?? $_SERVER['ALL_PROXY'] ?? null; + + if ('https:' === $url['scheme']) { + $proxy = $_SERVER['https_proxy'] ?? $_SERVER['HTTPS_PROXY'] ?? $proxy; + } + } + + if (null === $proxy) { return null; } @@ -662,7 +653,7 @@ trait HttpClientTrait throw new TransportException(sprintf('Unsupported proxy scheme "%s": "http" or "https" expected.', $proxy['scheme'])); } - $noProxy ??= $_SERVER['no_proxy'] ?? $_SERVER['NO_PROXY'] ?? ''; + $noProxy = $noProxy ?? $_SERVER['no_proxy'] ?? $_SERVER['NO_PROXY'] ?? ''; $noProxy = $noProxy ? preg_split('/[\s,]+/', $noProxy) : []; return [ @@ -672,22 +663,6 @@ trait HttpClientTrait ]; } - private static function getProxyUrl(?string $proxy, array $url): ?string - { - if (null !== $proxy) { - return $proxy; - } - - // Ignore HTTP_PROXY except on the CLI to work around httpoxy set of vulnerabilities - $proxy = $_SERVER['http_proxy'] ?? (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? $_SERVER['HTTP_PROXY'] ?? null : null) ?? $_SERVER['all_proxy'] ?? $_SERVER['ALL_PROXY'] ?? null; - - if ('https:' === $url['scheme']) { - $proxy = $_SERVER['https_proxy'] ?? $_SERVER['HTTPS_PROXY'] ?? $proxy; - } - - return $proxy; - } - private static function shouldBuffer(array $headers): bool { if (null === $contentType = $headers['content-type'][0] ?? null) { diff --git a/vendor/symfony/http-client/HttpOptions.php b/vendor/symfony/http-client/HttpOptions.php index a07fac7ed..d71b11926 100644 --- a/vendor/symfony/http-client/HttpOptions.php +++ b/vendor/symfony/http-client/HttpOptions.php @@ -32,7 +32,7 @@ class HttpOptions /** * @return $this */ - public function setAuthBasic(string $user, #[\SensitiveParameter] string $password = ''): static + public function setAuthBasic(string $user, string $password = ''): static { $this->options['auth_basic'] = $user; @@ -46,7 +46,7 @@ class HttpOptions /** * @return $this */ - public function setAuthBearer(#[\SensitiveParameter] string $token): static + public function setAuthBearer(string $token): static { $this->options['auth_bearer'] = $token; diff --git a/vendor/symfony/http-client/HttplugClient.php b/vendor/symfony/http-client/HttplugClient.php index 661f9fec0..676cfe6ae 100644 --- a/vendor/symfony/http-client/HttplugClient.php +++ b/vendor/symfony/http-client/HttplugClient.php @@ -46,11 +46,7 @@ if (!interface_exists(HttplugInterface::class)) { } if (!interface_exists(RequestFactory::class)) { - throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory".'); -} - -if (!interface_exists(RequestFactoryInterface::class)) { - throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as the "psr/http-factory" package is not installed. Try running "composer require nyholm/psr7".'); + throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "php-http/message-factory" package is not installed. Try running "composer require nyholm/psr7".'); } /** @@ -61,18 +57,18 @@ if (!interface_exists(RequestFactoryInterface::class)) { * * @author Nicolas Grekas */ -final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestFactoryInterface, StreamFactoryInterface, UriFactoryInterface, RequestFactory, StreamFactory, UriFactory, ResetInterface +final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestFactory, StreamFactory, UriFactory, ResetInterface { - private HttpClientInterface $client; - private ResponseFactoryInterface $responseFactory; - private StreamFactoryInterface $streamFactory; + private $client; + private $responseFactory; + private $streamFactory; /** * @var \SplObjectStorage|null */ private ?\SplObjectStorage $promisePool; - private HttplugWaitLoop $waitLoop; + private $waitLoop; public function __construct(HttpClientInterface $client = null, ResponseFactoryInterface $responseFactory = null, StreamFactoryInterface $streamFactory = null) { @@ -99,14 +95,9 @@ final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestF $this->waitLoop = new HttplugWaitLoop($this->client, $this->promisePool, $this->responseFactory, $this->streamFactory); } - public function withOptions(array $options): static - { - $clone = clone $this; - $clone->client = $clone->client->withOptions($options); - - return $clone; - } - + /** + * {@inheritdoc} + */ public function sendRequest(RequestInterface $request): Psr7ResponseInterface { try { @@ -116,6 +107,9 @@ final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestF } } + /** + * {@inheritdoc} + */ public function sendAsyncRequest(RequestInterface $request): HttplugPromise { if (!$promisePool = $this->promisePool) { @@ -155,14 +149,10 @@ final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestF } /** - * @param string $method - * @param UriInterface|string $uri + * {@inheritdoc} */ public function createRequest($method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1'): RequestInterface { - if (2 < \func_num_args()) { - trigger_deprecation('symfony/http-client', '6.2', 'Passing more than 2 arguments to "%s()" is deprecated.', __METHOD__); - } if ($this->responseFactory instanceof RequestFactoryInterface) { $request = $this->responseFactory->createRequest($method, $uri); } elseif (class_exists(Request::class)) { @@ -175,7 +165,7 @@ final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestF $request = $request ->withProtocolVersion($protocolVersion) - ->withBody($this->createStream($body ?? '')) + ->withBody($this->createStream($body)) ; foreach ($headers as $name => $value) { @@ -186,24 +176,20 @@ final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestF } /** - * @param string $content + * {@inheritdoc} */ - public function createStream($content = ''): StreamInterface + public function createStream($body = null): StreamInterface { - if (!\is_string($content)) { - trigger_deprecation('symfony/http-client', '6.2', 'Passing a "%s" to "%s()" is deprecated, use "createStreamFrom*()" instead.', get_debug_type($content), __METHOD__); + if ($body instanceof StreamInterface) { + return $body; } - if ($content instanceof StreamInterface) { - return $content; - } - - if (\is_string($content ?? '')) { - $stream = $this->streamFactory->createStream($content ?? ''); - } elseif (\is_resource($content)) { - $stream = $this->streamFactory->createStreamFromResource($content); + if (\is_string($body ?? '')) { + $stream = $this->streamFactory->createStream($body ?? ''); + } elseif (\is_resource($body)) { + $stream = $this->streamFactory->createStreamFromResource($body); } else { - throw new \InvalidArgumentException(sprintf('"%s()" expects string, resource or StreamInterface, "%s" given.', __METHOD__, get_debug_type($content))); + throw new \InvalidArgumentException(sprintf('"%s()" expects string, resource or StreamInterface, "%s" given.', __METHOD__, get_debug_type($body))); } if ($stream->isSeekable()) { @@ -213,25 +199,11 @@ final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestF return $stream; } - public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface - { - return $this->streamFactory->createStreamFromFile($filename, $mode); - } - - public function createStreamFromResource($resource): StreamInterface - { - return $this->streamFactory->createStreamFromResource($resource); - } - /** - * @param string $uri + * {@inheritdoc} */ - public function createUri($uri = ''): UriInterface + public function createUri($uri): UriInterface { - if (!\is_string($uri)) { - trigger_deprecation('symfony/http-client', '6.2', 'Passing a "%s" to "%s()" is deprecated, pass a string instead.', get_debug_type($uri), __METHOD__); - } - if ($uri instanceof UriInterface) { return $uri; } diff --git a/vendor/symfony/http-client/Internal/AmpBody.php b/vendor/symfony/http-client/Internal/AmpBody.php index bd995e17d..a6ff7635b 100644 --- a/vendor/symfony/http-client/Internal/AmpBody.php +++ b/vendor/symfony/http-client/Internal/AmpBody.php @@ -25,7 +25,7 @@ use Symfony\Component\HttpClient\Exception\TransportException; */ class AmpBody implements RequestBody, InputStream { - private ResourceInputStream|\Closure|string $body; + private $body; private array $info; private \Closure $onProgress; private ?int $offset = 0; diff --git a/vendor/symfony/http-client/Internal/AmpClientState.php b/vendor/symfony/http-client/Internal/AmpClientState.php index 18a1722c3..28906e629 100644 --- a/vendor/symfony/http-client/Internal/AmpClientState.php +++ b/vendor/symfony/http-client/Internal/AmpClientState.php @@ -49,12 +49,12 @@ final class AmpClientState extends ClientState private \Closure $clientConfigurator; private int $maxHostConnections; private int $maxPendingPushes; - private ?LoggerInterface $logger; + private $logger; public function __construct(?callable $clientConfigurator, int $maxHostConnections, int $maxPendingPushes, ?LoggerInterface &$logger) { $clientConfigurator ??= static fn (PooledHttpClient $client) => new InterceptedHttpClient($client, new RetryRequests(2)); - $this->clientConfigurator = $clientConfigurator(...); + $this->clientConfigurator = $clientConfigurator instanceof \Closure ? $clientConfigurator : \Closure::fromCallable($clientConfigurator); $this->maxHostConnections = $maxHostConnections; $this->maxPendingPushes = $maxPendingPushes; @@ -76,7 +76,7 @@ final class AmpClientState extends ClientState foreach ($options['proxy']['no_proxy'] as $rule) { $dotRule = '.'.ltrim($rule, '.'); - if ('*' === $rule || $host === $rule || str_ends_with($host, $dotRule)) { + if ('*' === $rule || $host === $rule || substr($host, -\strlen($dotRule)) === $dotRule) { $options['proxy'] = null; break; } @@ -200,11 +200,11 @@ final class AmpClientState extends ClientState if ($this->maxPendingPushes <= \count($this->pushedResponses[$authority] ?? [])) { $fifoUrl = key($this->pushedResponses[$authority]); unset($this->pushedResponses[$authority][$fifoUrl]); - $this->logger?->debug(sprintf('Evicting oldest pushed response: "%s"', $fifoUrl)); + $this->logger && $this->logger->debug(sprintf('Evicting oldest pushed response: "%s"', $fifoUrl)); } $url = (string) $request->getUri(); - $this->logger?->debug(sprintf('Queueing pushed response: "%s"', $url)); + $this->logger && $this->logger->debug(sprintf('Queueing pushed response: "%s"', $url)); $this->pushedResponses[$authority][] = [$url, $deferred, $request, $response, [ 'proxy' => $options['proxy'], 'bindto' => $options['bindto'], diff --git a/vendor/symfony/http-client/Internal/AmpListener.php b/vendor/symfony/http-client/Internal/AmpListener.php index 206c44982..37c43d148 100644 --- a/vendor/symfony/http-client/Internal/AmpListener.php +++ b/vendor/symfony/http-client/Internal/AmpListener.php @@ -50,7 +50,7 @@ class AmpListener implements EventListener public function startRequest(Request $request): Promise { - $this->info['start_time'] ??= microtime(true); + $this->info['start_time'] = $this->info['start_time'] ?? microtime(true); ($this->onProgress)(); return new Success(); @@ -81,7 +81,7 @@ class AmpListener implements EventListener { $host = $stream->getRemoteAddress()->getHost(); - if (str_contains($host, ':')) { + if (false !== strpos($host, ':')) { $host = '['.$host.']'; } diff --git a/vendor/symfony/http-client/Internal/CurlClientState.php b/vendor/symfony/http-client/Internal/CurlClientState.php index 8e2a42ed0..2934fc863 100644 --- a/vendor/symfony/http-client/Internal/CurlClientState.php +++ b/vendor/symfony/http-client/Internal/CurlClientState.php @@ -25,7 +25,6 @@ final class CurlClientState extends ClientState { public ?\CurlMultiHandle $handle; public ?\CurlShareHandle $share; - public bool $performing = false; /** @var PushedResponse[] */ public array $pushedResponses = []; @@ -39,7 +38,7 @@ final class CurlClientState extends ClientState public function __construct(int $maxHostConnections, int $maxPendingPushes) { - self::$curlVersion ??= curl_version(); + self::$curlVersion = self::$curlVersion ?? curl_version(); $this->handle = curl_multi_init(); $this->dnsCache = new DnsCache(); @@ -83,7 +82,7 @@ final class CurlClientState extends ClientState public function reset() { foreach ($this->pushedResponses as $url => $response) { - $this->logger?->debug(sprintf('Unused pushed response: "%s"', $url)); + $this->logger && $this->logger->debug(sprintf('Unused pushed response: "%s"', $url)); curl_multi_remove_handle($this->handle, $response->handle); curl_close($response->handle); } @@ -114,7 +113,7 @@ final class CurlClientState extends ClientState } if (!isset($headers[':method']) || !isset($headers[':scheme']) || !isset($headers[':authority']) || !isset($headers[':path'])) { - $this->logger?->debug(sprintf('Rejecting pushed response from "%s": pushed headers are invalid', $origin)); + $this->logger && $this->logger->debug(sprintf('Rejecting pushed response from "%s": pushed headers are invalid', $origin)); return \CURL_PUSH_DENY; } @@ -125,7 +124,7 @@ final class CurlClientState extends ClientState // but this is a MUST in the HTTP/2 RFC; let's restrict pushes to the original host, // ignoring domains mentioned as alt-name in the certificate for now (same as curl). if (!str_starts_with($origin, $url.'/')) { - $this->logger?->debug(sprintf('Rejecting pushed response from "%s": server is not authoritative for "%s"', $origin, $url)); + $this->logger && $this->logger->debug(sprintf('Rejecting pushed response from "%s": server is not authoritative for "%s"', $origin, $url)); return \CURL_PUSH_DENY; } @@ -133,11 +132,11 @@ final class CurlClientState extends ClientState if ($maxPendingPushes <= \count($this->pushedResponses)) { $fifoUrl = key($this->pushedResponses); unset($this->pushedResponses[$fifoUrl]); - $this->logger?->debug(sprintf('Evicting oldest pushed response: "%s"', $fifoUrl)); + $this->logger && $this->logger->debug(sprintf('Evicting oldest pushed response: "%s"', $fifoUrl)); } $url .= $headers[':path'][0]; - $this->logger?->debug(sprintf('Queueing pushed response: "%s"', $url)); + $this->logger && $this->logger->debug(sprintf('Queueing pushed response: "%s"', $url)); $this->pushedResponses[$url] = new PushedResponse(new CurlResponse($this, $pushed), $headers, $this->openHandles[(int) $parent][1] ?? [], $pushed); diff --git a/vendor/symfony/http-client/Internal/HttplugWaitLoop.php b/vendor/symfony/http-client/Internal/HttplugWaitLoop.php index 85d7e01d6..e3685c4d4 100644 --- a/vendor/symfony/http-client/Internal/HttplugWaitLoop.php +++ b/vendor/symfony/http-client/Internal/HttplugWaitLoop.php @@ -30,10 +30,10 @@ use Symfony\Contracts\HttpClient\ResponseInterface; */ final class HttplugWaitLoop { - private HttpClientInterface $client; + private $client; private ?\SplObjectStorage $promisePool; - private ResponseFactoryInterface $responseFactory; - private StreamFactoryInterface $streamFactory; + private $responseFactory; + private $streamFactory; /** * @param \SplObjectStorage|null $promisePool @@ -120,11 +120,7 @@ final class HttplugWaitLoop foreach ($response->getHeaders(false) as $name => $values) { foreach ($values as $value) { - try { - $psrResponse = $psrResponse->withAddedHeader($name, $value); - } catch (\InvalidArgumentException $e) { - // ignore invalid header - } + $psrResponse = $psrResponse->withAddedHeader($name, $value); } } diff --git a/vendor/symfony/http-client/Internal/PushedResponse.php b/vendor/symfony/http-client/Internal/PushedResponse.php index f1e0ad687..51c94e9ba 100644 --- a/vendor/symfony/http-client/Internal/PushedResponse.php +++ b/vendor/symfony/http-client/Internal/PushedResponse.php @@ -22,7 +22,7 @@ use Symfony\Component\HttpClient\Response\CurlResponse; */ final class PushedResponse { - public CurlResponse $response; + public $response; /** @var string[] */ public array $requestHeaders; diff --git a/vendor/symfony/http-client/LICENSE b/vendor/symfony/http-client/LICENSE index 7536caeae..99757d517 100644 --- a/vendor/symfony/http-client/LICENSE +++ b/vendor/symfony/http-client/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2023 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/http-client/MockHttpClient.php b/vendor/symfony/http-client/MockHttpClient.php index 7906b9a96..ecb2423d5 100644 --- a/vendor/symfony/http-client/MockHttpClient.php +++ b/vendor/symfony/http-client/MockHttpClient.php @@ -28,7 +28,7 @@ class MockHttpClient implements HttpClientInterface, ResetInterface { use HttpClientTrait; - private ResponseInterface|\Closure|iterable|null $responseFactory; + private $responseFactory; private int $requestsCount = 0; private array $defaultOptions = []; @@ -56,9 +56,12 @@ class MockHttpClient implements HttpClientInterface, ResetInterface })(); } - $this->responseFactory = !\is_callable($responseFactory) ? $responseFactory : $responseFactory(...); + $this->responseFactory = !\is_callable($responseFactory) || $responseFactory instanceof \Closure ? $responseFactory : \Closure::fromCallable($responseFactory); } + /** + * {@inheritdoc} + */ public function request(string $method, string $url, array $options = []): ResponseInterface { [$url, $options] = $this->prepareRequest($method, $url, $options, $this->defaultOptions, true); @@ -78,12 +81,15 @@ class MockHttpClient implements HttpClientInterface, ResetInterface ++$this->requestsCount; if (!$response instanceof ResponseInterface) { - throw new TransportException(sprintf('The response factory passed to MockHttpClient must return/yield an instance of ResponseInterface, "%s" given.', get_debug_type($response))); + throw new TransportException(sprintf('The response factory passed to MockHttpClient must return/yield an instance of ResponseInterface, "%s" given.', \is_object($response) ? \get_class($response) : \gettype($response))); } return MockResponse::fromRequest($method, $url, $options, $response); } + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { if ($responses instanceof ResponseInterface) { @@ -98,6 +104,9 @@ class MockHttpClient implements HttpClientInterface, ResetInterface return $this->requestsCount; } + /** + * {@inheritdoc} + */ public function withOptions(array $options): static { $clone = clone $this; diff --git a/vendor/symfony/http-client/NativeHttpClient.php b/vendor/symfony/http-client/NativeHttpClient.php index 734effbb4..83625ae51 100644 --- a/vendor/symfony/http-client/NativeHttpClient.php +++ b/vendor/symfony/http-client/NativeHttpClient.php @@ -39,7 +39,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac private array $defaultOptions = self::OPTIONS_DEFAULTS; private static array $emptyDefaults = self::OPTIONS_DEFAULTS; - private NativeClientState $multi; + private $multi; /** * @param array $defaultOptions Default request's options @@ -49,7 +49,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac */ public function __construct(array $defaultOptions = [], int $maxHostConnections = 6) { - $this->defaultOptions['buffer'] ??= self::shouldBuffer(...); + $this->defaultOptions['buffer'] = $this->defaultOptions['buffer'] ?? \Closure::fromCallable([__CLASS__, 'shouldBuffer']); if ($defaultOptions) { [, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, $this->defaultOptions); @@ -61,6 +61,8 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac /** * @see HttpClientInterface::OPTIONS_DEFAULTS for available options + * + * {@inheritdoc} */ public function request(string $method, string $url, array $options = []): ResponseInterface { @@ -187,7 +189,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac $this->multi->dnsCache = $options['resolve'] + $this->multi->dnsCache; } - $this->logger?->info(sprintf('Request: "%s %s"', $method, implode('', $url))); + $this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, implode('', $url))); if (!isset($options['normalized_headers']['user-agent'])) { $options['headers'][] = 'User-Agent: Symfony HttpClient/Native'; @@ -246,12 +248,15 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac $url['authority'] = substr_replace($url['authority'], $ip, -\strlen($host) - \strlen($port), \strlen($host)); } - return [self::createRedirectResolver($options, $host, $port, $proxy, $info, $onProgress), implode('', $url)]; + return [self::createRedirectResolver($options, $host, $proxy, $info, $onProgress), implode('', $url)]; }; return new NativeResponse($this->multi, $context, implode('', $url), $options, $info, $resolver, $onProgress, $this->logger); } + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { if ($responses instanceof NativeResponse) { @@ -337,11 +342,11 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac /** * Handles redirects - the native logic is too buggy to be used. */ - private static function createRedirectResolver(array $options, string $host, string $port, ?array $proxy, array &$info, ?\Closure $onProgress): \Closure + private static function createRedirectResolver(array $options, string $host, ?array $proxy, array &$info, ?\Closure $onProgress): \Closure { $redirectHeaders = []; if (0 < $maxRedirects = $options['max_redirects']) { - $redirectHeaders = ['host' => $host, 'port' => $port]; + $redirectHeaders = ['host' => $host]; $redirectHeaders['with_auth'] = $redirectHeaders['no_auth'] = array_filter($options['headers'], static function ($h) { return 0 !== stripos($h, 'Host:'); }); @@ -362,7 +367,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac try { $url = self::parseUrl($location); - } catch (InvalidArgumentException) { + } catch (InvalidArgumentException $e) { $info['redirect_url'] = null; return null; @@ -401,7 +406,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac if (false !== (parse_url($location, \PHP_URL_HOST) ?? false)) { // Authorization and Cookie headers MUST NOT follow except for the initial host name - $requestHeaders = $redirectHeaders['host'] === $host && $redirectHeaders['port'] === $port ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth']; + $requestHeaders = $redirectHeaders['host'] === $host ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth']; $requestHeaders[] = 'Host: '.$host.$port; $dnsResolve = !self::configureHeadersAndProxy($context, $host, $requestHeaders, $proxy, 'https:' === $url['scheme']); } else { diff --git a/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php b/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php index 89885abe1..d3ea5ad5e 100644 --- a/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php +++ b/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php @@ -45,7 +45,7 @@ final class NoPrivateNetworkHttpClient implements HttpClientInterface, LoggerAwa '::/128', ]; - private HttpClientInterface $client; + private $client; private string|array|null $subnets; /** @@ -62,6 +62,9 @@ final class NoPrivateNetworkHttpClient implements HttpClientInterface, LoggerAwa $this->subnets = $subnets; } + /** + * {@inheritdoc} + */ public function request(string $method, string $url, array $options = []): ResponseInterface { $onProgress = $options['on_progress'] ?? null; @@ -87,11 +90,17 @@ final class NoPrivateNetworkHttpClient implements HttpClientInterface, LoggerAwa return $this->client->request($method, $url, $options); } + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { return $this->client->stream($responses, $timeout); } + /** + * {@inheritdoc} + */ public function setLogger(LoggerInterface $logger): void { if ($this->client instanceof LoggerAwareInterface) { @@ -99,6 +108,9 @@ final class NoPrivateNetworkHttpClient implements HttpClientInterface, LoggerAwa } } + /** + * {@inheritdoc} + */ public function withOptions(array $options): static { $clone = clone $this; diff --git a/vendor/symfony/http-client/Psr18Client.php b/vendor/symfony/http-client/Psr18Client.php index 699acf449..650c28570 100644 --- a/vendor/symfony/http-client/Psr18Client.php +++ b/vendor/symfony/http-client/Psr18Client.php @@ -52,9 +52,9 @@ if (!interface_exists(ClientInterface::class)) { */ final class Psr18Client implements ClientInterface, RequestFactoryInterface, StreamFactoryInterface, UriFactoryInterface, ResetInterface { - private HttpClientInterface $client; - private ResponseFactoryInterface $responseFactory; - private StreamFactoryInterface $streamFactory; + private $client; + private $responseFactory; + private $streamFactory; public function __construct(HttpClientInterface $client = null, ResponseFactoryInterface $responseFactory = null, StreamFactoryInterface $streamFactory = null) { @@ -79,14 +79,9 @@ final class Psr18Client implements ClientInterface, RequestFactoryInterface, Str $this->streamFactory = $streamFactory; } - public function withOptions(array $options): static - { - $clone = clone $this; - $clone->client = $clone->client->withOptions($options); - - return $clone; - } - + /** + * {@inheritdoc} + */ public function sendRequest(RequestInterface $request): ResponseInterface { try { @@ -136,6 +131,9 @@ final class Psr18Client implements ClientInterface, RequestFactoryInterface, Str } } + /** + * {@inheritdoc} + */ public function createRequest(string $method, $uri): RequestInterface { if ($this->responseFactory instanceof RequestFactoryInterface) { @@ -153,6 +151,9 @@ final class Psr18Client implements ClientInterface, RequestFactoryInterface, Str throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__)); } + /** + * {@inheritdoc} + */ public function createStream(string $content = ''): StreamInterface { $stream = $this->streamFactory->createStream($content); @@ -164,16 +165,25 @@ final class Psr18Client implements ClientInterface, RequestFactoryInterface, Str return $stream; } + /** + * {@inheritdoc} + */ public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface { return $this->streamFactory->createStreamFromFile($filename, $mode); } + /** + * {@inheritdoc} + */ public function createStreamFromResource($resource): StreamInterface { return $this->streamFactory->createStreamFromResource($resource); } + /** + * {@inheritdoc} + */ public function createUri(string $uri = ''): UriInterface { if ($this->responseFactory instanceof UriFactoryInterface) { @@ -204,7 +214,7 @@ final class Psr18Client implements ClientInterface, RequestFactoryInterface, Str */ class Psr18NetworkException extends \RuntimeException implements NetworkExceptionInterface { - private RequestInterface $request; + private $request; public function __construct(TransportExceptionInterface $e, RequestInterface $request) { @@ -223,7 +233,7 @@ class Psr18NetworkException extends \RuntimeException implements NetworkExceptio */ class Psr18RequestException extends \InvalidArgumentException implements RequestExceptionInterface { - private RequestInterface $request; + private $request; public function __construct(TransportExceptionInterface $e, RequestInterface $request) { diff --git a/vendor/symfony/http-client/README.md b/vendor/symfony/http-client/README.md index 214489b7e..0c55ccc11 100644 --- a/vendor/symfony/http-client/README.md +++ b/vendor/symfony/http-client/README.md @@ -3,6 +3,16 @@ HttpClient component The HttpClient component provides powerful methods to fetch HTTP resources synchronously or asynchronously. +Sponsor +------- + +The Httpclient component for Symfony 5.4/6.0 is [backed][1] by [Klaxoon][2]. + +Klaxoon is a platform that empowers organizations to run effective and +productive workshops easily in a hybrid environment. Anytime, Anywhere. + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -11,3 +21,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://klaxoon.com +[3]: https://symfony.com/sponsor diff --git a/vendor/symfony/http-client/Response/AmpResponse.php b/vendor/symfony/http-client/Response/AmpResponse.php index 9aad82641..cea7102ea 100644 --- a/vendor/symfony/http-client/Response/AmpResponse.php +++ b/vendor/symfony/http-client/Response/AmpResponse.php @@ -45,8 +45,9 @@ final class AmpResponse implements ResponseInterface, StreamableInterface private static string $nextId = 'a'; - private AmpClientState $multi; + private $multi; private ?array $options; + private $canceller; private \Closure $onProgress; private static ?string $delay = null; @@ -72,14 +73,13 @@ final class AmpResponse implements ResponseInterface, StreamableInterface $info = &$this->info; $headers = &$this->headers; - $canceller = new CancellationTokenSource(); + $canceller = $this->canceller = new CancellationTokenSource(); $handle = &$this->handle; $info['url'] = (string) $request->getUri(); $info['http_method'] = $request->getMethod(); $info['start_time'] = null; $info['redirect_url'] = null; - $info['original_url'] = $info['url']; $info['redirect_time'] = 0.0; $info['redirect_count'] = 0; $info['size_upload'] = 0.0; @@ -136,6 +136,9 @@ final class AmpResponse implements ResponseInterface, StreamableInterface }); } + /** + * {@inheritdoc} + */ public function getInfo(string $type = null): mixed { return null !== $type ? $this->info[$type] ?? null : $this->info; @@ -164,6 +167,9 @@ final class AmpResponse implements ResponseInterface, StreamableInterface } } + /** + * {@inheritdoc} + */ private static function schedule(self $response, array &$runningResponses): void { if (isset($runningResponses[0])) { @@ -179,6 +185,8 @@ final class AmpResponse implements ResponseInterface, StreamableInterface } /** + * {@inheritdoc} + * * @param AmpClientState $multi */ private static function perform(ClientState $multi, array &$responses = null): void @@ -199,6 +207,8 @@ final class AmpResponse implements ResponseInterface, StreamableInterface } /** + * {@inheritdoc} + * * @param AmpClientState $multi */ private static function select(ClientState $multi, float $timeout): int @@ -206,7 +216,7 @@ final class AmpResponse implements ResponseInterface, StreamableInterface $timeout += microtime(true); self::$delay = Loop::defer(static function () use ($timeout) { if (0 < $timeout -= microtime(true)) { - self::$delay = Loop::delay(ceil(1000 * $timeout), Loop::stop(...)); + self::$delay = Loop::delay(ceil(1000 * $timeout), [Loop::class, 'stop']); } else { Loop::stop(); } @@ -217,7 +227,7 @@ final class AmpResponse implements ResponseInterface, StreamableInterface return null === self::$delay ? 1 : 0; } - private static function generateResponse(Request $request, AmpClientState $multi, string $id, array &$info, array &$headers, CancellationTokenSource $canceller, array &$options, \Closure $onProgress, &$handle, ?LoggerInterface $logger, Promise &$pause): \Generator + private static function generateResponse(Request $request, AmpClientState $multi, string $id, array &$info, array &$headers, CancellationTokenSource $canceller, array &$options, \Closure $onProgress, &$handle, ?LoggerInterface $logger, Promise &$pause) { $request->setInformationalResponseHandler(static function (Response $response) use ($multi, $id, &$info, &$headers) { self::addResponseHeaders($response, $info, $headers); @@ -228,7 +238,7 @@ final class AmpResponse implements ResponseInterface, StreamableInterface try { /* @var Response $response */ if (null === $response = yield from self::getPushedResponse($request, $multi, $info, $headers, $options, $logger)) { - $logger?->info(sprintf('Request: "%s %s"', $info['http_method'], $info['url'])); + $logger && $logger->info(sprintf('Request: "%s %s"', $info['http_method'], $info['url'])); $response = yield from self::followRedirects($request, $multi, $info, $headers, $canceller, $options, $onProgress, $handle, $logger, $pause); } @@ -276,7 +286,7 @@ final class AmpResponse implements ResponseInterface, StreamableInterface self::stopLoop(); } - private static function followRedirects(Request $originRequest, AmpClientState $multi, array &$info, array &$headers, CancellationTokenSource $canceller, array $options, \Closure $onProgress, &$handle, ?LoggerInterface $logger, Promise &$pause): \Generator + private static function followRedirects(Request $originRequest, AmpClientState $multi, array &$info, array &$headers, CancellationTokenSource $canceller, array $options, \Closure $onProgress, &$handle, ?LoggerInterface $logger, Promise &$pause) { yield $pause; @@ -300,11 +310,11 @@ final class AmpResponse implements ResponseInterface, StreamableInterface }; try { - $previousUrl ??= $urlResolver::parseUrl($info['url']); + $previousUrl = $previousUrl ?? $urlResolver::parseUrl($info['url']); $location = $urlResolver::parseUrl($location); $location = $urlResolver::resolveUrl($location, $previousUrl); $info['redirect_url'] = implode('', $location); - } catch (InvalidArgumentException) { + } catch (InvalidArgumentException $e) { return $response; } @@ -312,13 +322,13 @@ final class AmpResponse implements ResponseInterface, StreamableInterface return $response; } - $logger?->info(sprintf('Redirecting: "%s %s"', $status, $info['url'])); + $logger && $logger->info(sprintf('Redirecting: "%s %s"', $status, $info['url'])); try { // Discard body of redirects while (null !== yield $response->getBody()->read()) { } - } catch (HttpException|StreamException) { + } catch (HttpException|StreamException $e) { // Ignore streaming errors on previous responses } @@ -348,7 +358,7 @@ final class AmpResponse implements ResponseInterface, StreamableInterface } foreach ($originRequest->getRawHeaders() as [$name, $value]) { - $request->addHeader($name, $value); + $request->setHeader($name, $value); } if ($request->getUri()->getAuthority() !== $originRequest->getUri()->getAuthority()) { @@ -390,7 +400,7 @@ final class AmpResponse implements ResponseInterface, StreamableInterface /** * Accepts pushed responses only if their headers related to authentication match the request. */ - private static function getPushedResponse(Request $request, AmpClientState $multi, array &$info, array &$headers, array $options, ?LoggerInterface $logger): \Generator + private static function getPushedResponse(Request $request, AmpClientState $multi, array &$info, array &$headers, array $options, ?LoggerInterface $logger) { if ('' !== $options['body']) { return null; @@ -420,14 +430,14 @@ final class AmpResponse implements ResponseInterface, StreamableInterface foreach ($response->getHeaderArray('vary') as $vary) { foreach (preg_split('/\s*+,\s*+/', $vary) as $v) { if ('*' === $v || ($pushedRequest->getHeaderArray($v) !== $request->getHeaderArray($v) && 'accept-encoding' !== strtolower($v))) { - $logger?->debug(sprintf('Skipping pushed response: "%s"', $info['url'])); + $logger && $logger->debug(sprintf('Skipping pushed response: "%s"', $info['url'])); continue 3; } } } $pushDeferred->resolve(); - $logger?->debug(sprintf('Accepting pushed response: "%s %s"', $info['http_method'], $info['url'])); + $logger && $logger->debug(sprintf('Accepting pushed response: "%s %s"', $info['http_method'], $info['url'])); self::addResponseHeaders($response, $info, $headers); unset($multi->pushedResponses[$authority][$i]); @@ -446,6 +456,6 @@ final class AmpResponse implements ResponseInterface, StreamableInterface self::$delay = null; } - Loop::defer(Loop::stop(...)); + Loop::defer([Loop::class, 'stop']); } } diff --git a/vendor/symfony/http-client/Response/AsyncContext.php b/vendor/symfony/http-client/Response/AsyncContext.php index 55903463a..7fd815d52 100644 --- a/vendor/symfony/http-client/Response/AsyncContext.php +++ b/vendor/symfony/http-client/Response/AsyncContext.php @@ -26,8 +26,8 @@ use Symfony\Contracts\HttpClient\ResponseInterface; final class AsyncContext { private $passthru; - private HttpClientInterface $client; - private ResponseInterface $response; + private $client; + private $response; private array $info = []; private $content; private int $offset; diff --git a/vendor/symfony/http-client/Response/AsyncResponse.php b/vendor/symfony/http-client/Response/AsyncResponse.php index 8236623b2..14c080e9f 100644 --- a/vendor/symfony/http-client/Response/AsyncResponse.php +++ b/vendor/symfony/http-client/Response/AsyncResponse.php @@ -34,8 +34,8 @@ final class AsyncResponse implements ResponseInterface, StreamableInterface private const FIRST_CHUNK_YIELDED = 1; private const LAST_CHUNK_YIELDED = 2; - private ?HttpClientInterface $client; - private ResponseInterface $response; + private $client; + private $response; private array $info = ['canceled' => false]; private $passthru; private $stream; @@ -123,6 +123,9 @@ final class AsyncResponse implements ResponseInterface, StreamableInterface return $this->info + $this->response->getInfo(); } + /** + * {@inheritdoc} + */ public function toStream(bool $throw = true) { if ($throw) { @@ -143,6 +146,9 @@ final class AsyncResponse implements ResponseInterface, StreamableInterface return $stream; } + /** + * {@inheritdoc} + */ public function cancel(): void { if ($this->info['canceled']) { @@ -165,7 +171,7 @@ final class AsyncResponse implements ResponseInterface, StreamableInterface } $this->passthru = null; - } catch (ExceptionInterface) { + } catch (ExceptionInterface $e) { // ignore any errors when canceling } } @@ -190,7 +196,7 @@ final class AsyncResponse implements ResponseInterface, StreamableInterface foreach (self::passthru($this->client, $this, new LastChunk()) as $chunk) { // no-op } - } catch (ExceptionInterface) { + } catch (ExceptionInterface $e) { // ignore any errors when destructing } } diff --git a/vendor/symfony/http-client/Response/CommonResponseTrait.php b/vendor/symfony/http-client/Response/CommonResponseTrait.php index 06f6b7d88..448b85424 100644 --- a/vendor/symfony/http-client/Response/CommonResponseTrait.php +++ b/vendor/symfony/http-client/Response/CommonResponseTrait.php @@ -35,6 +35,9 @@ trait CommonResponseTrait private int $offset = 0; private ?array $jsonData = null; + /** + * {@inheritdoc} + */ public function getContent(bool $throw = true): string { if ($this->initializer) { @@ -72,6 +75,9 @@ trait CommonResponseTrait return stream_get_contents($this->content); } + /** + * {@inheritdoc} + */ public function toArray(bool $throw = true): array { if ('' === $content = $this->getContent($throw)) { @@ -100,6 +106,9 @@ trait CommonResponseTrait return $content; } + /** + * {@inheritdoc} + */ public function toStream(bool $throw = true) { if ($throw) { diff --git a/vendor/symfony/http-client/Response/CurlResponse.php b/vendor/symfony/http-client/Response/CurlResponse.php index 9c151546a..ae18d5840 100644 --- a/vendor/symfony/http-client/Response/CurlResponse.php +++ b/vendor/symfony/http-client/Response/CurlResponse.php @@ -32,7 +32,8 @@ final class CurlResponse implements ResponseInterface, StreamableInterface } use TransportResponseTrait; - private CurlClientState $multi; + private static bool $performing = false; + private $multi; /** * @var resource @@ -42,7 +43,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface /** * @internal */ - public function __construct(CurlClientState $multi, \CurlHandle|string $ch, array $options = null, LoggerInterface $logger = null, string $method = 'GET', callable $resolveRedirect = null, int $curlVersion = null, string $originalUrl = null) + public function __construct(CurlClientState $multi, \CurlHandle|string $ch, array $options = null, LoggerInterface $logger = null, string $method = 'GET', callable $resolveRedirect = null, int $curlVersion = null) { $this->multi = $multi; @@ -67,8 +68,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface $this->info['http_method'] = $method; $this->info['user_data'] = $options['user_data'] ?? null; $this->info['max_duration'] = $options['max_duration'] ?? null; - $this->info['start_time'] ??= microtime(true); - $this->info['original_url'] = $originalUrl ?? $this->info['url'] ?? curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL); + $this->info['start_time'] = $this->info['start_time'] ?? microtime(true); $info = &$this->info; $headers = &$this->headers; $debugBuffer = $this->debugBuffer; @@ -79,7 +79,17 @@ final class CurlResponse implements ResponseInterface, StreamableInterface } curl_setopt($ch, \CURLOPT_HEADERFUNCTION, static function ($ch, string $data) use (&$info, &$headers, $options, $multi, $id, &$location, $resolveRedirect, $logger): int { - return self::parseHeaderLine($ch, $data, $info, $headers, $options, $multi, $id, $location, $resolveRedirect, $logger); + if (0 !== substr_compare($data, "\r\n", -2)) { + return 0; + } + + $len = 0; + + foreach (explode("\r\n", substr($data, 0, -2)) as $data) { + $len += 2 + self::parseHeaderLine($ch, $data, $info, $headers, $options, $multi, $id, $location, $resolveRedirect, $logger); + } + + return $len; }); if (null === $options) { @@ -171,7 +181,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface unset($multi->pauseExpiries[$id], $multi->openHandles[$id], $multi->handlesActivity[$id]); curl_setopt($ch, \CURLOPT_PRIVATE, '_0'); - if ($multi->performing) { + if (self::$performing) { return; } @@ -193,6 +203,9 @@ final class CurlResponse implements ResponseInterface, StreamableInterface }); } + /** + * {@inheritdoc} + */ public function getInfo(string $type = null): mixed { if (!$info = $this->finalInfo) { @@ -221,15 +234,18 @@ final class CurlResponse implements ResponseInterface, StreamableInterface return null !== $type ? $info[$type] ?? null : $info; } + /** + * {@inheritdoc} + */ public function getContent(bool $throw = true): string { - $performing = $this->multi->performing; - $this->multi->performing = $performing || '_0' === curl_getinfo($this->handle, \CURLINFO_PRIVATE); + $performing = self::$performing; + self::$performing = $performing || '_0' === curl_getinfo($this->handle, \CURLINFO_PRIVATE); try { return $this->doGetContent($throw); } finally { - $this->multi->performing = $performing; + self::$performing = $performing; } } @@ -248,6 +264,9 @@ final class CurlResponse implements ResponseInterface, StreamableInterface } } + /** + * {@inheritdoc} + */ private static function schedule(self $response, array &$runningResponses): void { if (isset($runningResponses[$i = (int) $response->multi->handle])) { @@ -264,11 +283,13 @@ final class CurlResponse implements ResponseInterface, StreamableInterface } /** + * {@inheritdoc} + * * @param CurlClientState $multi */ private static function perform(ClientState $multi, array &$responses = null): void { - if ($multi->performing) { + if (self::$performing) { if ($responses) { $response = current($responses); $multi->handlesActivity[(int) $response->handle][] = null; @@ -279,7 +300,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface } try { - $multi->performing = true; + self::$performing = true; ++$multi->execCounter; $active = 0; while (\CURLM_CALL_MULTI_PERFORM === ($err = curl_multi_exec($multi->handle, $active))) { @@ -316,11 +337,13 @@ final class CurlResponse implements ResponseInterface, StreamableInterface $multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) ? null : new TransportException(ucfirst(curl_error($ch) ?: curl_strerror($result)).sprintf(' for "%s".', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL))); } } finally { - $multi->performing = false; + self::$performing = false; } } /** + * {@inheritdoc} + * * @param CurlClientState $multi */ private static function select(ClientState $multi, float $timeout): int @@ -356,29 +379,19 @@ final class CurlResponse implements ResponseInterface, StreamableInterface */ private static function parseHeaderLine($ch, string $data, array &$info, array &$headers, ?array $options, CurlClientState $multi, int $id, ?string &$location, ?callable $resolveRedirect, ?LoggerInterface $logger): int { - if (!str_ends_with($data, "\r\n")) { - return 0; - } - $waitFor = @curl_getinfo($ch, \CURLINFO_PRIVATE) ?: '_0'; if ('H' !== $waitFor[0]) { return \strlen($data); // Ignore HTTP trailers } - $statusCode = curl_getinfo($ch, \CURLINFO_RESPONSE_CODE); - - if ($statusCode !== $info['http_code'] && !preg_match("#^HTTP/\d+(?:\.\d+)? {$statusCode}(?: |\r\n$)#", $data)) { - return \strlen($data); // Ignore headers from responses to CONNECT requests - } - - if ("\r\n" !== $data) { + if ('' !== $data) { // Regular header line: add it to the list - self::addResponseHeaders([substr($data, 0, -2)], $info, $headers); + self::addResponseHeaders([$data], $info, $headers); if (!str_starts_with($data, 'HTTP/')) { if (0 === stripos($data, 'Location:')) { - $location = trim(substr($data, 9, -2)); + $location = trim(substr($data, 9)); } return \strlen($data); @@ -401,7 +414,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface // End of headers: handle informational responses, redirects, etc. - if (200 > $statusCode) { + if (200 > $statusCode = curl_getinfo($ch, \CURLINFO_RESPONSE_CODE)) { $multi->handlesActivity[$id][] = new InformationalChunk($statusCode, $headers); $location = null; diff --git a/vendor/symfony/http-client/Response/HttplugPromise.php b/vendor/symfony/http-client/Response/HttplugPromise.php index deaea720d..09ed10df3 100644 --- a/vendor/symfony/http-client/Response/HttplugPromise.php +++ b/vendor/symfony/http-client/Response/HttplugPromise.php @@ -23,7 +23,7 @@ use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface; */ final class HttplugPromise implements HttplugPromiseInterface { - private GuzzlePromiseInterface $promise; + private $promise; public function __construct(GuzzlePromiseInterface $promise) { @@ -43,12 +43,17 @@ final class HttplugPromise implements HttplugPromiseInterface $this->promise->cancel(); } + /** + * {@inheritdoc} + */ public function getState(): string { return $this->promise->getState(); } /** + * {@inheritdoc} + * * @return Psr7ResponseInterface|mixed */ public function wait($unwrap = true): mixed diff --git a/vendor/symfony/http-client/Response/MockResponse.php b/vendor/symfony/http-client/Response/MockResponse.php index 24089013f..496b7bee5 100644 --- a/vendor/symfony/http-client/Response/MockResponse.php +++ b/vendor/symfony/http-client/Response/MockResponse.php @@ -39,9 +39,9 @@ class MockResponse implements ResponseInterface, StreamableInterface private static int $idSequence = 0; /** - * @param string|iterable $body The response body as a string or an iterable of strings, - * yielding an empty string simulates an idle timeout, - * throwing or yielding an exception yields an ErrorChunk + * @param string|string[]|iterable $body The response body as a string or an iterable of strings, + * yielding an empty string simulates an idle timeout, + * throwing an exception yields an ErrorChunk * * @see ResponseInterface::getInfo() for possible info, e.g. "response_headers" */ @@ -90,11 +90,17 @@ class MockResponse implements ResponseInterface, StreamableInterface return $this->requestMethod; } + /** + * {@inheritdoc} + */ public function getInfo(string $type = null): mixed { return null !== $type ? $this->info[$type] ?? null : $this->info; } + /** + * {@inheritdoc} + */ public function cancel(): void { $this->info['canceled'] = true; @@ -104,12 +110,11 @@ class MockResponse implements ResponseInterface, StreamableInterface } catch (TransportException $e) { // ignore errors when canceling } - - $onProgress = $this->requestOptions['on_progress'] ?? static function () {}; - $dlSize = isset($this->headers['content-encoding']) || 'HEAD' === ($this->info['http_method'] ?? null) || \in_array($this->info['http_code'], [204, 304], true) ? 0 : (int) ($this->headers['content-length'][0] ?? 0); - $onProgress($this->offset, $dlSize, $this->info); } + /** + * {@inheritdoc} + */ protected function close(): void { $this->inflate = null; @@ -137,7 +142,6 @@ class MockResponse implements ResponseInterface, StreamableInterface $response->info['user_data'] = $options['user_data'] ?? null; $response->info['max_duration'] = $options['max_duration'] ?? null; $response->info['url'] = $url; - $response->info['original_url'] = $url; if ($mock instanceof self) { $mock->requestOptions = $response->requestOptions; @@ -151,13 +155,16 @@ class MockResponse implements ResponseInterface, StreamableInterface return $response; } + /** + * {@inheritdoc} + */ protected static function schedule(self $response, array &$runningResponses): void { if (!isset($response->id)) { throw new InvalidArgumentException('MockResponse instances must be issued by MockHttpClient before processing.'); } - $multi = self::$mainMulti ??= new ClientState(); + $multi = self::$mainMulti ?? self::$mainMulti = new ClientState(); if (!isset($runningResponses[0])) { $runningResponses[0] = [$multi, []]; @@ -166,6 +173,9 @@ class MockResponse implements ResponseInterface, StreamableInterface $runningResponses[0][1][$response->id] = $response; } + /** + * {@inheritdoc} + */ protected static function perform(ClientState $multi, array &$responses): void { foreach ($responses as $response) { @@ -209,6 +219,9 @@ class MockResponse implements ResponseInterface, StreamableInterface } } + /** + * {@inheritdoc} + */ protected static function select(ClientState $multi, float $timeout): int { return 42; @@ -217,7 +230,7 @@ class MockResponse implements ResponseInterface, StreamableInterface /** * Simulates sending the request. */ - private static function writeRequest(self $response, array $options, ResponseInterface $mock): void + private static function writeRequest(self $response, array $options, ResponseInterface $mock) { $onProgress = $options['on_progress'] ?? static function () {}; $response->info += $mock->getInfo() ?: []; @@ -260,7 +273,7 @@ class MockResponse implements ResponseInterface, StreamableInterface /** * Simulates reading the response. */ - private static function readResponse(self $response, array $options, ResponseInterface $mock, int &$offset): void + private static function readResponse(self $response, array $options, ResponseInterface $mock, int &$offset) { $onProgress = $options['on_progress'] ?? static function () {}; @@ -294,10 +307,6 @@ class MockResponse implements ResponseInterface, StreamableInterface if (!\is_string($body)) { try { foreach ($body as $chunk) { - if ($chunk instanceof \Throwable) { - throw $chunk; - } - if ('' === $chunk = (string) $chunk) { // simulate an idle timeout $response->body[] = new ErrorChunk($offset, sprintf('Idle timeout reached for "%s".', $response->info['url'])); diff --git a/vendor/symfony/http-client/Response/NativeResponse.php b/vendor/symfony/http-client/Response/NativeResponse.php index a6b9dd989..96f1256a1 100644 --- a/vendor/symfony/http-client/Response/NativeResponse.php +++ b/vendor/symfony/http-client/Response/NativeResponse.php @@ -43,7 +43,7 @@ final class NativeResponse implements ResponseInterface, StreamableInterface */ private $buffer; - private NativeClientState $multi; + private $multi; private float $pauseExpiry = 0.0; /** @@ -66,7 +66,6 @@ final class NativeResponse implements ResponseInterface, StreamableInterface // Temporary resource to dechunk the response stream $this->buffer = fopen('php://temp', 'w+'); - $info['original_url'] = implode('', $info['url']); $info['user_data'] = $options['user_data']; $info['max_duration'] = $options['max_duration']; ++$multi->responseCount; @@ -88,6 +87,9 @@ final class NativeResponse implements ResponseInterface, StreamableInterface }); } + /** + * {@inheritdoc} + */ public function getInfo(string $type = null): mixed { if (!$info = $this->finalInfo) { @@ -125,7 +127,7 @@ final class NativeResponse implements ResponseInterface, StreamableInterface throw new TransportException($msg); } - $this->logger?->info(sprintf('%s for "%s".', $msg, $url ?? $this->url)); + $this->logger && $this->logger->info(sprintf('%s for "%s".', $msg, $url ?? $this->url)); }); try { @@ -161,7 +163,7 @@ final class NativeResponse implements ResponseInterface, StreamableInterface break; } - $this->logger?->info(sprintf('Redirecting: "%s %s"', $this->info['http_code'], $url ?? $this->url)); + $this->logger && $this->logger->info(sprintf('Redirecting: "%s %s"', $this->info['http_code'], $url ?? $this->url)); } } catch (\Throwable $e) { $this->close(); @@ -206,12 +208,18 @@ final class NativeResponse implements ResponseInterface, StreamableInterface $this->multi->hosts[$host] = 1 + ($this->multi->hosts[$host] ?? 0); } + /** + * {@inheritdoc} + */ private function close(): void { $this->canary->cancel(); $this->handle = $this->buffer = $this->inflate = $this->onProgress = null; } + /** + * {@inheritdoc} + */ private static function schedule(self $response, array &$runningResponses): void { if (!isset($runningResponses[$i = $response->multi->id])) { @@ -228,6 +236,8 @@ final class NativeResponse implements ResponseInterface, StreamableInterface } /** + * {@inheritdoc} + * * @param NativeClientState $multi */ private static function perform(ClientState $multi, array &$responses = null): void @@ -337,6 +347,8 @@ final class NativeResponse implements ResponseInterface, StreamableInterface } /** + * {@inheritdoc} + * * @param NativeClientState $multi */ private static function select(ClientState $multi, float $timeout): int @@ -353,7 +365,7 @@ final class NativeResponse implements ResponseInterface, StreamableInterface continue; } - if ($pauseExpiry && ($now ??= microtime(true)) < $pauseExpiry) { + if ($pauseExpiry && ($now ?? $now = microtime(true)) < $pauseExpiry) { $timeout = min($timeout, $pauseExpiry - $now); continue; } diff --git a/vendor/symfony/http-client/Response/StreamWrapper.php b/vendor/symfony/http-client/Response/StreamWrapper.php index f891313dd..3768e2e06 100644 --- a/vendor/symfony/http-client/Response/StreamWrapper.php +++ b/vendor/symfony/http-client/Response/StreamWrapper.php @@ -25,9 +25,9 @@ class StreamWrapper /** @var resource|null */ public $context; - private HttpClientInterface|ResponseInterface $client; + private $client; - private ResponseInterface $response; + private $response; /** @var resource|string|null */ private $content; @@ -116,7 +116,7 @@ class StreamWrapper return false; } - public function stream_read(int $count): string|false + public function stream_read(int $count) { if (\is_resource($this->content)) { // Empty the internal activity list @@ -174,7 +174,9 @@ class StreamWrapper if ('' !== $data = $chunk->getContent()) { if (\strlen($data) > $count) { - $this->content ??= substr($data, $count); + if (null === $this->content) { + $this->content = substr($data, $count); + } $data = substr($data, 0, $count); } $this->offset += \strlen($data); diff --git a/vendor/symfony/http-client/Response/TraceableResponse.php b/vendor/symfony/http-client/Response/TraceableResponse.php index 507799e14..f8a7ceedc 100644 --- a/vendor/symfony/http-client/Response/TraceableResponse.php +++ b/vendor/symfony/http-client/Response/TraceableResponse.php @@ -31,10 +31,10 @@ use Symfony\Contracts\HttpClient\ResponseInterface; */ class TraceableResponse implements ResponseInterface, StreamableInterface { - private HttpClientInterface $client; - private ResponseInterface $response; + private $client; + private $response; private mixed $content; - private ?StopwatchEvent $event; + private $event; public function __construct(HttpClientInterface $client, ResponseInterface $response, &$content, StopwatchEvent $event = null) { @@ -59,7 +59,7 @@ class TraceableResponse implements ResponseInterface, StreamableInterface try { $this->response->__destruct(); } finally { - if ($this->event?->isStarted()) { + if ($this->event && $this->event->isStarted()) { $this->event->stop(); } } @@ -70,7 +70,7 @@ class TraceableResponse implements ResponseInterface, StreamableInterface try { return $this->response->getStatusCode(); } finally { - if ($this->event?->isStarted()) { + if ($this->event && $this->event->isStarted()) { $this->event->lap(); } } @@ -81,7 +81,7 @@ class TraceableResponse implements ResponseInterface, StreamableInterface try { return $this->response->getHeaders($throw); } finally { - if ($this->event?->isStarted()) { + if ($this->event && $this->event->isStarted()) { $this->event->lap(); } } @@ -96,7 +96,7 @@ class TraceableResponse implements ResponseInterface, StreamableInterface return $this->content = $this->response->getContent(false); } finally { - if ($this->event?->isStarted()) { + if ($this->event && $this->event->isStarted()) { $this->event->stop(); } if ($throw) { @@ -114,7 +114,7 @@ class TraceableResponse implements ResponseInterface, StreamableInterface return $this->content = $this->response->toArray(false); } finally { - if ($this->event?->isStarted()) { + if ($this->event && $this->event->isStarted()) { $this->event->stop(); } if ($throw) { @@ -127,7 +127,7 @@ class TraceableResponse implements ResponseInterface, StreamableInterface { $this->response->cancel(); - if ($this->event?->isStarted()) { + if ($this->event && $this->event->isStarted()) { $this->event->stop(); } } @@ -202,7 +202,7 @@ class TraceableResponse implements ResponseInterface, StreamableInterface } } - private function checkStatusCode(int $code): void + private function checkStatusCode(int $code) { if (500 <= $code) { throw new ServerException($this); diff --git a/vendor/symfony/http-client/Response/TransportResponseTrait.php b/vendor/symfony/http-client/Response/TransportResponseTrait.php index ac53b99a6..802ba83f2 100644 --- a/vendor/symfony/http-client/Response/TransportResponseTrait.php +++ b/vendor/symfony/http-client/Response/TransportResponseTrait.php @@ -11,13 +11,11 @@ namespace Symfony\Component\HttpClient\Response; -use Psr\Log\LoggerInterface; use Symfony\Component\HttpClient\Chunk\DataChunk; use Symfony\Component\HttpClient\Chunk\ErrorChunk; use Symfony\Component\HttpClient\Chunk\FirstChunk; use Symfony\Component\HttpClient\Chunk\LastChunk; use Symfony\Component\HttpClient\Exception\TransportException; -use Symfony\Component\HttpClient\Internal\Canary; use Symfony\Component\HttpClient\Internal\ClientState; /** @@ -29,7 +27,7 @@ use Symfony\Component\HttpClient\Internal\ClientState; */ trait TransportResponseTrait { - private Canary $canary; + private $canary; private array $headers = []; private array $info = [ 'response_headers' => [], @@ -42,10 +40,13 @@ trait TransportResponseTrait private $handle; private int|string $id; private ?float $timeout = 0; - private \InflateContext|bool|null $inflate = null; + private $inflate = null; private ?array $finalInfo = null; - private ?LoggerInterface $logger = null; + private $logger = null; + /** + * {@inheritdoc} + */ public function getStatusCode(): int { if ($this->initializer) { @@ -55,6 +56,9 @@ trait TransportResponseTrait return $this->info['http_code']; } + /** + * {@inheritdoc} + */ public function getHeaders(bool $throw = true): array { if ($this->initializer) { @@ -68,6 +72,9 @@ trait TransportResponseTrait return $this->headers; } + /** + * {@inheritdoc} + */ public function cancel(): void { $this->info['canceled'] = true; @@ -122,7 +129,7 @@ trait TransportResponseTrait /** * Ensures the request is always sent and that the response code was checked. */ - private function doDestruct(): void + private function doDestruct() { $this->shouldBuffer = true; @@ -182,7 +189,7 @@ trait TransportResponseTrait continue; } elseif ($elapsedTimeout >= $timeoutMax) { $multi->handlesActivity[$j] = [new ErrorChunk($response->offset, sprintf('Idle timeout reached for "%s".', $response->getInfo('url')))]; - $multi->lastTimeout ??= $lastActivity; + $multi->lastTimeout ?? $multi->lastTimeout = $lastActivity; } else { continue; } diff --git a/vendor/symfony/http-client/Retry/GenericRetryStrategy.php b/vendor/symfony/http-client/Retry/GenericRetryStrategy.php index edbf2c066..9d1473c34 100644 --- a/vendor/symfony/http-client/Retry/GenericRetryStrategy.php +++ b/vendor/symfony/http-client/Retry/GenericRetryStrategy.php @@ -102,7 +102,7 @@ class GenericRetryStrategy implements RetryStrategyInterface $delay = $this->delayMs * $this->multiplier ** $context->getInfo('retry_count'); if ($this->jitter > 0) { - $randomness = (int) ($delay * $this->jitter); + $randomness = $delay * $this->jitter; $delay = $delay + random_int(-$randomness, +$randomness); } diff --git a/vendor/symfony/http-client/RetryableHttpClient.php b/vendor/symfony/http-client/RetryableHttpClient.php index d0c13165b..71d0a8cf5 100644 --- a/vendor/symfony/http-client/RetryableHttpClient.php +++ b/vendor/symfony/http-client/RetryableHttpClient.php @@ -32,9 +32,9 @@ class RetryableHttpClient implements HttpClientInterface, ResetInterface { use AsyncDecoratorTrait; - private RetryStrategyInterface $strategy; + private $strategy; private int $maxRetries; - private LoggerInterface $logger; + private $logger; /** * @param int $maxRetries The maximum number of times to retry diff --git a/vendor/symfony/http-client/ScopingHttpClient.php b/vendor/symfony/http-client/ScopingHttpClient.php index da8ef4c98..74bb82045 100644 --- a/vendor/symfony/http-client/ScopingHttpClient.php +++ b/vendor/symfony/http-client/ScopingHttpClient.php @@ -28,7 +28,7 @@ class ScopingHttpClient implements HttpClientInterface, ResetInterface, LoggerAw { use HttpClientTrait; - private HttpClientInterface $client; + private $client; private array $defaultOptionsByRegexp; private ?string $defaultRegexp; @@ -45,13 +45,18 @@ class ScopingHttpClient implements HttpClientInterface, ResetInterface, LoggerAw public static function forBaseUri(HttpClientInterface $client, string $baseUri, array $defaultOptions = [], string $regexp = null): self { - $regexp ??= preg_quote(implode('', self::resolveUrl(self::parseUrl('.'), self::parseUrl($baseUri)))); + if (null === $regexp) { + $regexp = preg_quote(implode('', self::resolveUrl(self::parseUrl('.'), self::parseUrl($baseUri)))); + } $defaultOptions['base_uri'] = $baseUri; return new self($client, [$regexp => $defaultOptions], $regexp); } + /** + * {@inheritdoc} + */ public function request(string $method, string $url, array $options = []): ResponseInterface { $e = null; @@ -88,6 +93,9 @@ class ScopingHttpClient implements HttpClientInterface, ResetInterface, LoggerAw return $this->client->request($method, $url, $options); } + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { return $this->client->stream($responses, $timeout); @@ -100,6 +108,9 @@ class ScopingHttpClient implements HttpClientInterface, ResetInterface, LoggerAw } } + /** + * {@inheritdoc} + */ public function setLogger(LoggerInterface $logger): void { if ($this->client instanceof LoggerAwareInterface) { @@ -107,6 +118,9 @@ class ScopingHttpClient implements HttpClientInterface, ResetInterface, LoggerAw } } + /** + * {@inheritdoc} + */ public function withOptions(array $options): static { $clone = clone $this; diff --git a/vendor/symfony/http-client/TraceableHttpClient.php b/vendor/symfony/http-client/TraceableHttpClient.php index b9df9732a..bca2859d4 100644 --- a/vendor/symfony/http-client/TraceableHttpClient.php +++ b/vendor/symfony/http-client/TraceableHttpClient.php @@ -26,8 +26,8 @@ use Symfony\Contracts\Service\ResetInterface; */ final class TraceableHttpClient implements HttpClientInterface, ResetInterface, LoggerAwareInterface { - private HttpClientInterface $client; - private ?Stopwatch $stopwatch; + private $client; + private $stopwatch; private \ArrayObject $tracedRequests; public function __construct(HttpClientInterface $client, Stopwatch $stopwatch = null) @@ -37,6 +37,9 @@ final class TraceableHttpClient implements HttpClientInterface, ResetInterface, $this->tracedRequests = new \ArrayObject(); } + /** + * {@inheritdoc} + */ public function request(string $method, string $url, array $options = []): ResponseInterface { $content = null; @@ -63,9 +66,12 @@ final class TraceableHttpClient implements HttpClientInterface, ResetInterface, } }; - return new TraceableResponse($this->client, $this->client->request($method, $url, $options), $content, $this->stopwatch?->start("$method $url", 'http_client')); + return new TraceableResponse($this->client, $this->client->request($method, $url, $options), $content, null === $this->stopwatch ? null : $this->stopwatch->start("$method $url", 'http_client')); } + /** + * {@inheritdoc} + */ public function stream(ResponseInterface|iterable $responses, float $timeout = null): ResponseStreamInterface { if ($responses instanceof TraceableResponse) { @@ -89,6 +95,9 @@ final class TraceableHttpClient implements HttpClientInterface, ResetInterface, $this->tracedRequests->exchangeArray([]); } + /** + * {@inheritdoc} + */ public function setLogger(LoggerInterface $logger): void { if ($this->client instanceof LoggerAwareInterface) { @@ -96,6 +105,9 @@ final class TraceableHttpClient implements HttpClientInterface, ResetInterface, } } + /** + * {@inheritdoc} + */ public function withOptions(array $options): static { $clone = clone $this; diff --git a/vendor/symfony/http-client/composer.json b/vendor/symfony/http-client/composer.json index 34a1714bf..02a7653b5 100644 --- a/vendor/symfony/http-client/composer.json +++ b/vendor/symfony/http-client/composer.json @@ -2,7 +2,6 @@ "name": "symfony/http-client", "type": "library", "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", - "keywords": ["http"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ @@ -22,9 +21,8 @@ "symfony/http-client-implementation": "3.0" }, "require": { - "php": ">=8.1", + "php": ">=8.0.2", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.1|^3", "symfony/http-client-contracts": "^3", "symfony/service-contracts": "^1.0|^2|^3" }, @@ -36,7 +34,6 @@ "guzzlehttp/promises": "^1.4", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", - "php-http/message-factory": "^1.0", "psr/http-client": "^1.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", diff --git a/vendor/symfony/http-foundation/BinaryFileResponse.php b/vendor/symfony/http-foundation/BinaryFileResponse.php index 08bd03bf6..8990c9111 100644 --- a/vendor/symfony/http-foundation/BinaryFileResponse.php +++ b/vendor/symfony/http-foundation/BinaryFileResponse.php @@ -224,7 +224,7 @@ class BinaryFileResponse extends Response $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); foreach ($parts as $part) { [$pathPrefix, $location] = $part; - if (str_starts_with($path, $pathPrefix)) { + if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) { $path = $location.substr($path, \strlen($pathPrefix)); // Only set X-Accel-Redirect header if a valid URI can be produced // as nginx does not serve arbitrary file paths. diff --git a/vendor/symfony/http-foundation/CHANGELOG.md b/vendor/symfony/http-foundation/CHANGELOG.md index fdbd39cea..b528419d3 100644 --- a/vendor/symfony/http-foundation/CHANGELOG.md +++ b/vendor/symfony/http-foundation/CHANGELOG.md @@ -1,12 +1,6 @@ CHANGELOG ========= -6.1 ---- - - * Add stale while revalidate and stale if error cache header - * Allow dynamic session "ttl" when using a remote storage - 6.0 --- diff --git a/vendor/symfony/http-foundation/Cookie.php b/vendor/symfony/http-foundation/Cookie.php index b6166d70e..fb2853046 100644 --- a/vendor/symfony/http-foundation/Cookie.php +++ b/vendor/symfony/http-foundation/Cookie.php @@ -87,7 +87,7 @@ class Cookie * * @throws \InvalidArgumentException */ - public function __construct(string $name, string $value = null, int|string|\DateTimeInterface $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX) + public function __construct(string $name, string $value = null, int|string|\DateTimeInterface $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax') { // from PHP source code if ($raw && false !== strpbrk($name, self::RESERVED_CHARS_LIST)) { @@ -244,12 +244,12 @@ class Cookie $str .= '='; if ('' === (string) $this->getValue()) { - $str .= 'deleted; expires='.gmdate('D, d M Y H:i:s T', time() - 31536001).'; Max-Age=0'; + $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0'; } else { $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); if (0 !== $this->getExpiresTime()) { - $str .= '; expires='.gmdate('D, d M Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); + $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); } } diff --git a/vendor/symfony/http-foundation/ExpressionRequestMatcher.php b/vendor/symfony/http-foundation/ExpressionRequestMatcher.php index f2a07307d..9dbf2f743 100644 --- a/vendor/symfony/http-foundation/ExpressionRequestMatcher.php +++ b/vendor/symfony/http-foundation/ExpressionRequestMatcher.php @@ -21,8 +21,8 @@ use Symfony\Component\ExpressionLanguage\ExpressionLanguage; */ class ExpressionRequestMatcher extends RequestMatcher { - private ExpressionLanguage $language; - private Expression|string $expression; + private $language; + private $expression; public function setExpression(ExpressionLanguage $language, Expression|string $expression) { diff --git a/vendor/symfony/http-foundation/IpUtils.php b/vendor/symfony/http-foundation/IpUtils.php index 8f78d1b1d..51c698e4e 100644 --- a/vendor/symfony/http-foundation/IpUtils.php +++ b/vendor/symfony/http-foundation/IpUtils.php @@ -168,7 +168,7 @@ class IpUtils public static function anonymize(string $ip): string { $wrappedIPv6 = false; - if (str_starts_with($ip, '[') && str_ends_with($ip, ']')) { + if ('[' === substr($ip, 0, 1) && ']' === substr($ip, -1, 1)) { $wrappedIPv6 = true; $ip = substr($ip, 1, -1); } diff --git a/vendor/symfony/http-foundation/README.md b/vendor/symfony/http-foundation/README.md index 5cf900744..424f2c4f0 100644 --- a/vendor/symfony/http-foundation/README.md +++ b/vendor/symfony/http-foundation/README.md @@ -4,6 +4,16 @@ HttpFoundation Component The HttpFoundation component defines an object-oriented layer for the HTTP specification. +Sponsor +------- + +The HttpFoundation component for Symfony 5.4/6.0 is [backed][1] by [Laravel][2]. + +Laravel is a PHP web development framework that is passionate about maximum developer +happiness. Laravel is built using a variety of bespoke and Symfony based components. + +Help Symfony by [sponsoring][3] its development! + Resources --------- @@ -12,3 +22,7 @@ Resources * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://laravel.com/ +[3]: https://symfony.com/sponsor diff --git a/vendor/symfony/http-foundation/Request.php b/vendor/symfony/http-foundation/Request.php index b39b9c062..a20e9af15 100644 --- a/vendor/symfony/http-foundation/Request.php +++ b/vendor/symfony/http-foundation/Request.php @@ -690,8 +690,6 @@ class Request /** * Gets the Session. - * - * @throws SessionNotFoundException When session is not set properly */ public function getSession(): SessionInterface { @@ -1876,7 +1874,7 @@ class Request if (class_exists(\Locale::class, false)) { \Locale::setDefault($locale); } - } catch (\Exception) { + } catch (\Exception $e) { } } diff --git a/vendor/symfony/http-foundation/Response.php b/vendor/symfony/http-foundation/Response.php index 80fedc19b..c48efdfb7 100644 --- a/vendor/symfony/http-foundation/Response.php +++ b/vendor/symfony/http-foundation/Response.php @@ -98,8 +98,6 @@ class Response 'proxy_revalidate' => false, 'max_age' => true, 's_maxage' => true, - 'stale_if_error' => true, // RFC5861 - 'stale_while_revalidate' => true, // RFC5861 'immutable' => false, 'last_modified' => true, 'etag' => true, @@ -701,7 +699,7 @@ class Response { try { return $this->headers->getDate('Expires'); - } catch (\RuntimeException) { + } catch (\RuntimeException $e) { // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past return \DateTime::createFromFormat('U', time() - 172800); } @@ -776,38 +774,6 @@ class Response return $this; } - /** - * Sets the number of seconds after which the response should no longer be returned by shared caches when backend is down. - * - * This method sets the Cache-Control stale-if-error directive. - * - * @return $this - * - * @final - */ - public function setStaleIfError(int $value): static - { - $this->headers->addCacheControlDirective('stale-if-error', $value); - - return $this; - } - - /** - * Sets the number of seconds after which the response should no longer return stale content by shared caches. - * - * This method sets the Cache-Control stale-while-revalidate directive. - * - * @return $this - * - * @final - */ - public function setStaleWhileRevalidate(int $value): static - { - $this->headers->addCacheControlDirective('stale-while-revalidate', $value); - - return $this; - } - /** * Sets the number of seconds after which the response should no longer be considered fresh by shared caches. * @@ -981,14 +947,6 @@ class Response $this->setSharedMaxAge($options['s_maxage']); } - if (isset($options['stale_while_revalidate'])) { - $this->setStaleWhileRevalidate($options['stale_while_revalidate']); - } - - if (isset($options['stale_if_error'])) { - $this->setStaleIfError($options['stale_if_error']); - } - foreach (self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES as $directive => $hasValue) { if (!$hasValue && isset($options[$directive])) { if ($options[$directive]) { diff --git a/vendor/symfony/http-foundation/Session/Session.php b/vendor/symfony/http-foundation/Session/Session.php index 4e17e7efc..3254f1885 100644 --- a/vendor/symfony/http-foundation/Session/Session.php +++ b/vendor/symfony/http-foundation/Session/Session.php @@ -43,13 +43,13 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null, callable $usageReporter = null) { $this->storage = $storage ?? new NativeSessionStorage(); - $this->usageReporter = null === $usageReporter ? null : $usageReporter(...); + $this->usageReporter = $usageReporter instanceof \Closure || !\is_callable($usageReporter) ? $usageReporter : \Closure::fromCallable($usageReporter); - $attributes ??= new AttributeBag(); + $attributes = $attributes ?? new AttributeBag(); $this->attributeName = $attributes->getName(); $this->registerBag($attributes); - $flashes ??= new FlashBag(); + $flashes = $flashes ?? new FlashBag(); $this->flashName = $flashes->getName(); $this->registerBag($flashes); } diff --git a/vendor/symfony/http-foundation/Session/SessionBagProxy.php b/vendor/symfony/http-foundation/Session/SessionBagProxy.php index 76dfed724..1d405e3c7 100644 --- a/vendor/symfony/http-foundation/Session/SessionBagProxy.php +++ b/vendor/symfony/http-foundation/Session/SessionBagProxy.php @@ -18,7 +18,7 @@ namespace Symfony\Component\HttpFoundation\Session; */ final class SessionBagProxy implements SessionBagInterface { - private SessionBagInterface $bag; + private $bag; private array $data; private ?int $usageIndex; private ?\Closure $usageReporter; @@ -28,7 +28,7 @@ final class SessionBagProxy implements SessionBagInterface $this->bag = $bag; $this->data = &$data; $this->usageIndex = &$usageIndex; - $this->usageReporter = null === $usageReporter ? null : $usageReporter(...); + $this->usageReporter = $usageReporter instanceof \Closure || !\is_callable($usageReporter) ? $usageReporter : \Closure::fromCallable($usageReporter); } public function getBag(): SessionBagInterface diff --git a/vendor/symfony/http-foundation/Session/SessionFactory.php b/vendor/symfony/http-foundation/Session/SessionFactory.php index cdb6af51e..ffbd82cc4 100644 --- a/vendor/symfony/http-foundation/Session/SessionFactory.php +++ b/vendor/symfony/http-foundation/Session/SessionFactory.php @@ -22,15 +22,15 @@ class_exists(Session::class); */ class SessionFactory implements SessionFactoryInterface { - private RequestStack $requestStack; - private SessionStorageFactoryInterface $storageFactory; + private $requestStack; + private $storageFactory; private ?\Closure $usageReporter; public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, callable $usageReporter = null) { $this->requestStack = $requestStack; $this->storageFactory = $storageFactory; - $this->usageReporter = null === $usageReporter ? null : $usageReporter(...); + $this->usageReporter = $usageReporter instanceof \Closure || !\is_callable($usageReporter) ? $usageReporter : \Closure::fromCallable($usageReporter); } public function createSession(): SessionInterface diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php index 9962fef3d..377d1e090 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php @@ -18,8 +18,8 @@ use Symfony\Component\Cache\Marshaller\MarshallerInterface; */ class MarshallingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface { - private AbstractSessionHandler $handler; - private MarshallerInterface $marshaller; + private $handler; + private $marshaller; public function __construct(AbstractSessionHandler $handler, MarshallerInterface $marshaller) { diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php index 04c1afdd3..b61a6d0e9 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -21,12 +21,12 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; */ class MemcachedSessionHandler extends AbstractSessionHandler { - private \Memcached $memcached; + private $memcached; /** * Time to live in seconds. */ - private int|\Closure|null $ttl; + private ?int $ttl; /** * Key prefix for shared environments. @@ -84,7 +84,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler private function getCompatibleTtl(): int { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); + $ttl = (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')); // If the relative TTL that is used exceeds 30 days, memcached will treat the value as Unix time. // We have to convert it to an absolute Unix time at this point, to make sure the TTL is correct. diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php index c95537777..f4886dd9c 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -26,10 +26,9 @@ use MongoDB\Collection; */ class MongoDbSessionHandler extends AbstractSessionHandler { - private Client $mongo; - private Collection $collection; + private $mongo; + private $collection; private array $options; - private int|\Closure|null $ttl; /** * Constructor. @@ -40,8 +39,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler * * id_field: The field name for storing the session id [default: _id] * * data_field: The field name for storing the session data [default: data] * * time_field: The field name for storing the timestamp [default: time] - * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at] - * * ttl: The time to live in seconds. + * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at]. * * It is strongly recommended to put an index on the `expiry_field` for * garbage-collection. Alternatively it's possible to automatically expire @@ -76,7 +74,6 @@ class MongoDbSessionHandler extends AbstractSessionHandler 'time_field' => 'time', 'expiry_field' => 'expires_at', ], $options); - $this->ttl = $this->options['ttl'] ?? null; } public function close(): bool @@ -108,8 +105,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data): bool { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); - $expiry = new UTCDateTime((time() + (int) $ttl) * 1000); + $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); $fields = [ $this->options['time_field'] => new UTCDateTime(), @@ -128,8 +124,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler public function updateTimestamp(string $sessionId, string $data): bool { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); - $expiry = new UTCDateTime((time() + (int) $ttl) * 1000); + $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); $this->getCollection()->updateOne( [$this->options['id_field'] => $sessionId], diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php index dd80145aa..40ac49d91 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php @@ -65,7 +65,7 @@ class PdoSessionHandler extends AbstractSessionHandler */ public const LOCK_TRANSACTIONAL = 2; - private \PDO $pdo; + private $pdo; /** * DSN string or null for session.save_path or false when lazy connection disabled. @@ -79,11 +79,6 @@ class PdoSessionHandler extends AbstractSessionHandler private string $lifetimeCol = 'sess_lifetime'; private string $timeCol = 'sess_time'; - /** - * Time to live in seconds. - */ - private int|\Closure|null $ttl; - /** * Username when lazy-connect. */ @@ -142,7 +137,6 @@ class PdoSessionHandler extends AbstractSessionHandler * * db_password: The password when lazy-connect [default: ''] * * db_connection_options: An array of driver-specific connection options [default: []] * * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL] - * * ttl: The time to live in seconds. * * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null * @@ -172,7 +166,6 @@ class PdoSessionHandler extends AbstractSessionHandler $this->password = $options['db_password'] ?? $this->password; $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions; $this->lockMode = $options['lock_mode'] ?? $this->lockMode; - $this->ttl = $options['ttl'] ?? null; } /** @@ -191,19 +184,30 @@ class PdoSessionHandler extends AbstractSessionHandler // connect if we are not yet $this->getConnection(); - $sql = match ($this->driver) { - // We use varbinary for the ID column because it prevents unwanted conversions: - // - character set conversions between server and client - // - trailing space removal - // - case-insensitivity - // - language processing like é == e - 'mysql' => "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB", - 'sqlite' => "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)", - 'pgsql' => "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)", - 'oci' => "CREATE TABLE $this->table ($this->idCol VARCHAR2(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)", - 'sqlsrv' => "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)", - default => throw new \DomainException(sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)), - }; + switch ($this->driver) { + case 'mysql': + // We use varbinary for the ID column because it prevents unwanted conversions: + // - character set conversions between server and client + // - trailing space removal + // - case-insensitivity + // - language processing like é == e + $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB"; + break; + case 'sqlite': + $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; + break; + case 'pgsql': + $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; + break; + case 'oci': + $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; + break; + case 'sqlsrv': + $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; + break; + default: + throw new \DomainException(sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)); + } try { $this->pdo->exec($sql); @@ -282,7 +286,7 @@ class PdoSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data): bool { - $maxlifetime = (int) (($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime')); + $maxlifetime = (int) \ini_get('session.gc_maxlifetime'); try { // We use a single MERGE SQL query when supported by the database. @@ -325,7 +329,7 @@ class PdoSessionHandler extends AbstractSessionHandler public function updateTimestamp(string $sessionId, string $data): bool { - $expiry = time() + (int) (($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime')); + $expiry = time() + (int) \ini_get('session.gc_maxlifetime'); try { $updateStmt = $this->pdo->prepare( @@ -450,7 +454,7 @@ class PdoSessionHandler extends AbstractSessionHandler // If "unix_socket" is not in the query, we continue with the same process as pgsql // no break case 'pgsql': - $dsn ??= 'pgsql:'; + $dsn ?? $dsn = 'pgsql:'; if (isset($params['host']) && '' !== $params['host']) { $dsn .= 'host='.$params['host'].';'; diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php index d4dc1b91a..f9f3ce6ed 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php @@ -23,7 +23,7 @@ use Symfony\Component\Cache\Traits\RedisProxy; */ class RedisSessionHandler extends AbstractSessionHandler { - private \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis; + private $redis; /** * Key prefix for shared environments. @@ -33,7 +33,7 @@ class RedisSessionHandler extends AbstractSessionHandler /** * Time to live in seconds. */ - private int|\Closure|null $ttl; + private ?int $ttl; /** * List of available options: @@ -66,8 +66,7 @@ class RedisSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data): bool { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); - $result = $this->redis->setEx($this->prefix.$sessionId, (int) $ttl, $data); + $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')), $data); return $result && !$result instanceof ErrorInterface; } @@ -82,7 +81,7 @@ class RedisSessionHandler extends AbstractSessionHandler if ($unlink) { try { $unlink = false !== $this->redis->unlink($this->prefix.$sessionId); - } catch (\Throwable) { + } catch (\Throwable $e) { $unlink = false; } } @@ -110,8 +109,6 @@ class RedisSessionHandler extends AbstractSessionHandler public function updateTimestamp(string $sessionId, string $data): bool { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); - - return $this->redis->expire($this->prefix.$sessionId, (int) $ttl); + return $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime'))); } } diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php b/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php index 9ad2a1090..19ff94c81 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php @@ -21,16 +21,11 @@ use Symfony\Component\Cache\Traits\RedisProxy; */ class SessionHandlerFactory { - public static function createHandler(object|string $connection, array $options = []): AbstractSessionHandler + public static function createHandler(object|string $connection): AbstractSessionHandler { - if ($query = \is_string($connection) ? parse_url($connection) : false) { - parse_str($query['query'] ?? '', $query); - - if (($options['ttl'] ?? null) instanceof \Closure) { - $query['ttl'] = $options['ttl']; - } + if ($options = \is_string($connection) ? parse_url($connection) : false) { + parse_str($options['query'] ?? '', $options); } - $options = ($query ?: []) + $options; switch (true) { case $connection instanceof \Redis: @@ -63,7 +58,7 @@ class SessionHandlerFactory $handlerClass = str_starts_with($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class; $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]); - return new $handlerClass($connection, array_intersect_key($options, ['prefix' => 1, 'ttl' => 1])); + return new $handlerClass($connection, array_intersect_key($options ?: [], ['prefix' => 1, 'ttl' => 1])); case str_starts_with($connection, 'pdo_oci://'): if (!class_exists(DriverManager::class)) { @@ -81,7 +76,7 @@ class SessionHandlerFactory case str_starts_with($connection, 'sqlsrv://'): case str_starts_with($connection, 'sqlite://'): case str_starts_with($connection, 'sqlite3://'): - return new PdoSessionHandler($connection, $options); + return new PdoSessionHandler($connection, $options ?: []); } throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', $connection)); diff --git a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php index 8ecf943dc..c354d12ae 100644 --- a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php +++ b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php @@ -23,7 +23,7 @@ class MockFileSessionStorageFactory implements SessionStorageFactoryInterface { private ?string $savePath; private string $name; - private ?MetadataBag $metaBag; + private $metaBag; /** * @see MockFileSessionStorage constructor. diff --git a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php index 08901284c..ea6c7de1e 100644 --- a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php +++ b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php @@ -23,8 +23,8 @@ class_exists(NativeSessionStorage::class); class NativeSessionStorageFactory implements SessionStorageFactoryInterface { private array $options; - private AbstractProxy|\SessionHandlerInterface|null $handler; - private ?MetadataBag $metaBag; + private $handler; + private $metaBag; private bool $secure; /** @@ -41,7 +41,7 @@ class NativeSessionStorageFactory implements SessionStorageFactoryInterface public function createStorage(?Request $request): SessionStorageInterface { $storage = new NativeSessionStorage($this->options, $this->handler, $this->metaBag); - if ($this->secure && $request?->isSecure()) { + if ($this->secure && $request && $request->isSecure()) { $storage->setOptions(['cookie_secure' => true]); } diff --git a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php index 5cc738024..cce1ec6c3 100644 --- a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php +++ b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php @@ -22,8 +22,8 @@ class_exists(PhpBridgeSessionStorage::class); */ class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface { - private AbstractProxy|\SessionHandlerInterface|null $handler; - private ?MetadataBag $metaBag; + private $handler; + private $metaBag; private bool $secure; public function __construct(AbstractProxy|\SessionHandlerInterface $handler = null, MetadataBag $metaBag = null, bool $secure = false) @@ -36,7 +36,7 @@ class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface public function createStorage(?Request $request): SessionStorageInterface { $storage = new PhpBridgeSessionStorage($this->handler, $this->metaBag); - if ($this->secure && $request?->isSecure()) { + if ($this->secure && $request && $request->isSecure()) { $storage->setOptions(['cookie_secure' => true]); } diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php index 765849960..cb9699c32 100644 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php @@ -22,7 +22,7 @@ use Symfony\Component\HttpFoundation\Response; */ final class ResponseFormatSame extends Constraint { - private Request $request; + private $request; private ?string $format; public function __construct(Request $request, ?string $format) diff --git a/vendor/symfony/http-foundation/UrlHelper.php b/vendor/symfony/http-foundation/UrlHelper.php index 42fcf0459..c15f101cd 100644 --- a/vendor/symfony/http-foundation/UrlHelper.php +++ b/vendor/symfony/http-foundation/UrlHelper.php @@ -20,8 +20,8 @@ use Symfony\Component\Routing\RequestContext; */ final class UrlHelper { - private RequestStack $requestStack; - private ?RequestContext $requestContext; + private $requestStack; + private $requestContext; public function __construct(RequestStack $requestStack, RequestContext $requestContext = null) { @@ -31,7 +31,7 @@ final class UrlHelper public function getAbsoluteUrl(string $path): string { - if (str_contains($path, '://') || str_starts_with($path, '//')) { + if (str_contains($path, '://') || '//' === substr($path, 0, 2)) { return $path; } @@ -60,7 +60,7 @@ final class UrlHelper public function getRelativePath(string $path): string { - if (str_contains($path, '://') || str_starts_with($path, '//')) { + if (str_contains($path, '://') || '//' === substr($path, 0, 2)) { return $path; } diff --git a/vendor/symfony/http-foundation/composer.json b/vendor/symfony/http-foundation/composer.json index 1b232eb54..42405d957 100644 --- a/vendor/symfony/http-foundation/composer.json +++ b/vendor/symfony/http-foundation/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=8.1", + "php": ">=8.0.2", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.1" }, diff --git a/vendor/symfony/mime/Address.php b/vendor/symfony/mime/Address.php index ce57f77ee..c3b7e16ed 100644 --- a/vendor/symfony/mime/Address.php +++ b/vendor/symfony/mime/Address.php @@ -42,7 +42,7 @@ final class Address public function __construct(string $address, string $name = '') { if (!class_exists(EmailValidator::class)) { - throw new LogicException(sprintf('The "%s" class cannot be used as it needs "%s". Try running "composer require egulias/email-validator".', __CLASS__, EmailValidator::class)); + throw new LogicException(sprintf('The "%s" class cannot be used as it needs "%s"; try running "composer require egulias/email-validator".', __CLASS__, EmailValidator::class)); } self::$validator ??= new EmailValidator(); @@ -92,7 +92,7 @@ final class Address return $address; } - if (!str_contains($address, '<')) { + if (false === strpos($address, '<')) { return new self($address); } diff --git a/vendor/symfony/mime/CHANGELOG.md b/vendor/symfony/mime/CHANGELOG.md index 41eb14a4e..b076e4e86 100644 --- a/vendor/symfony/mime/CHANGELOG.md +++ b/vendor/symfony/mime/CHANGELOG.md @@ -1,24 +1,6 @@ CHANGELOG ========= -6.3 ---- - - * Support detection of related parts if `Content-Id` is used instead of the name - * Add `TextPart::getDisposition()` - -6.2 ---- - - * Add `File` - * Deprecate `Email::attachPart()`, use `addPart()` instead - * Deprecate calling `Message::setBody()` without arguments - -6.1 ---- - - * Add `DataPart::getFilename()` and `DataPart::getContentType()` - 6.0 --- diff --git a/vendor/symfony/mime/CharacterStream.php b/vendor/symfony/mime/CharacterStream.php index 21d7bc5f0..2433c4489 100644 --- a/vendor/symfony/mime/CharacterStream.php +++ b/vendor/symfony/mime/CharacterStream.php @@ -72,22 +72,29 @@ final class CharacterStream $this->fixedWidth = 0; $this->map = ['p' => [], 'i' => []]; } else { - $this->fixedWidth = match ($charset) { + switch ($charset) { // 16 bits - 'ucs2', - 'ucs-2', - 'utf16', - 'utf-16' => 2, - // 32 bits - 'ucs4', - 'ucs-4', - 'utf32', - 'utf-32' => 4, - // 7-8 bit charsets: (us-)?ascii, (iso|iec)-?8859-?[0-9]+, windows-?125[0-9], cp-?[0-9]+, ansi, macintosh, + case 'ucs2': + case 'ucs-2': + case 'utf16': + case 'utf-16': + $this->fixedWidth = 2; + break; + + // 32 bits + case 'ucs4': + case 'ucs-4': + case 'utf32': + case 'utf-32': + $this->fixedWidth = 4; + break; + + // 7-8 bit charsets: (us-)?ascii, (iso|iec)-?8859-?[0-9]+, windows-?125[0-9], cp-?[0-9]+, ansi, macintosh, // koi-?7, koi-?8-?.+, mik, (cork|t1), v?iscii - // and fallback - default => 1, - }; + // and fallback + default: + $this->fixedWidth = 1; + } } if (\is_resource($input)) { $blocks = 16372; diff --git a/vendor/symfony/mime/Crypto/DkimSigner.php b/vendor/symfony/mime/Crypto/DkimSigner.php index 1d2005e5c..ce07747df 100644 --- a/vendor/symfony/mime/Crypto/DkimSigner.php +++ b/vendor/symfony/mime/Crypto/DkimSigner.php @@ -30,7 +30,7 @@ final class DkimSigner public const ALGO_SHA256 = 'rsa-sha256'; public const ALGO_ED25519 = 'ed25519-sha256'; // RFC 8463 - private \OpenSSLAsymmetricKey $key; + private $key; private string $domainName; private string $selector; private array $defaultOptions; diff --git a/vendor/symfony/mime/Crypto/SMimeEncrypter.php b/vendor/symfony/mime/Crypto/SMimeEncrypter.php index 7d5dfecd2..0ccf2cd5e 100644 --- a/vendor/symfony/mime/Crypto/SMimeEncrypter.php +++ b/vendor/symfony/mime/Crypto/SMimeEncrypter.php @@ -33,7 +33,7 @@ final class SMimeEncrypter extends SMime } if (\is_array($certificate)) { - $this->certs = array_map($this->normalizeFilePath(...), $certificate); + $this->certs = array_map([$this, 'normalizeFilePath'], $certificate); } else { $this->certs = $this->normalizeFilePath($certificate); } diff --git a/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php b/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php index 70fa78633..5b2e66b5c 100644 --- a/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php +++ b/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php @@ -23,7 +23,7 @@ use Symfony\Component\DependencyInjection\Reference; class AddMimeTypeGuesserPass implements CompilerPassInterface { /** - * @return void + * {@inheritdoc} */ public function process(ContainerBuilder $container) { diff --git a/vendor/symfony/mime/DraftEmail.php b/vendor/symfony/mime/DraftEmail.php deleted file mode 100644 index a60fea173..000000000 --- a/vendor/symfony/mime/DraftEmail.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -use Symfony\Component\Mime\Header\Headers; -use Symfony\Component\Mime\Part\AbstractPart; - -/** - * @author Kevin Bond - */ -class DraftEmail extends Email -{ - public function __construct(Headers $headers = null, AbstractPart $body = null) - { - parent::__construct($headers, $body); - - $this->getHeaders()->addTextHeader('X-Unsent', '1'); - } - - /** - * Override default behavior as draft emails do not require From/Sender/Date/Message-ID headers. - * These are added by the client that actually sends the email. - */ - public function getPreparedHeaders(): Headers - { - $headers = clone $this->getHeaders(); - - if (!$headers->has('MIME-Version')) { - $headers->addTextHeader('MIME-Version', '1.0'); - } - - $headers->remove('Bcc'); - - return $headers; - } -} diff --git a/vendor/symfony/mime/Email.php b/vendor/symfony/mime/Email.php index 7f3496d1f..cfbfa8e9d 100644 --- a/vendor/symfony/mime/Email.php +++ b/vendor/symfony/mime/Email.php @@ -14,7 +14,6 @@ namespace Symfony\Component\Mime; use Symfony\Component\Mime\Exception\LogicException; use Symfony\Component\Mime\Part\AbstractPart; use Symfony\Component\Mime\Part\DataPart; -use Symfony\Component\Mime\Part\File; use Symfony\Component\Mime\Part\Multipart\AlternativePart; use Symfony\Component\Mime\Part\Multipart\MixedPart; use Symfony\Component\Mime\Part\Multipart\RelatedPart; @@ -327,7 +326,14 @@ class Email extends Message */ public function attach($body, string $name = null, string $contentType = null): static { - return $this->addPart(new DataPart($body, $name, $contentType)); + if (!\is_string($body) && !\is_resource($body)) { + throw new \TypeError(sprintf('The body must be a string or a resource (got "%s").', get_debug_type($body))); + } + + $this->cachedBody = null; + $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; + + return $this; } /** @@ -335,7 +341,10 @@ class Email extends Message */ public function attachFromPath(string $path, string $name = null, string $contentType = null): static { - return $this->addPart(new DataPart(new File($path), $name, $contentType)); + $this->cachedBody = null; + $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; + + return $this; } /** @@ -345,46 +354,49 @@ class Email extends Message */ public function embed($body, string $name = null, string $contentType = null): static { - return $this->addPart((new DataPart($body, $name, $contentType))->asInline()); + if (!\is_string($body) && !\is_resource($body)) { + throw new \TypeError(sprintf('The body must be a string or a resource (got "%s").', get_debug_type($body))); + } + + $this->cachedBody = null; + $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; + + return $this; } /** * @return $this */ public function embedFromPath(string $path, string $name = null, string $contentType = null): static - { - return $this->addPart((new DataPart(new File($path), $name, $contentType))->asInline()); - } - - /** - * @return $this - * - * @deprecated since Symfony 6.2, use addPart() instead - */ - public function attachPart(DataPart $part): static - { - @trigger_deprecation('symfony/mime', '6.2', 'The "%s()" method is deprecated, use "addPart()" instead.', __METHOD__); - - return $this->addPart($part); - } - - /** - * @return $this - */ - public function addPart(DataPart $part): static { $this->cachedBody = null; - $this->attachments[] = $part; + $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; return $this; } /** - * @return DataPart[] + * @return $this + */ + public function attachPart(DataPart $part): static + { + $this->cachedBody = null; + $this->attachments[] = ['part' => $part]; + + return $this; + } + + /** + * @return array|DataPart[] */ public function getAttachments(): array { - return $this->attachments; + $parts = []; + foreach ($this->attachments as $attachment) { + $parts[] = $this->createDataPart($attachment); + } + + return $parts; } public function getBody(): AbstractPart @@ -396,25 +408,13 @@ class Email extends Message return $this->generateBody(); } - /** - * @return void - */ public function ensureValidity() - { - $this->ensureBodyValid(); - - if ('1' === $this->getHeaders()->getHeaderBody('X-Unsent')) { - throw new LogicException('Cannot send messages marked as "draft".'); - } - - parent::ensureValidity(); - } - - private function ensureBodyValid(): void { if (null === $this->text && null === $this->html && !$this->attachments) { throw new LogicException('A message must have a text or an HTML part or attachments.'); } + + parent::ensureValidity(); } /** @@ -443,7 +443,7 @@ class Email extends Message return $this->cachedBody; } - $this->ensureBodyValid(); + $this->ensureValidity(); [$htmlPart, $otherParts, $relatedParts] = $this->prepareParts(); @@ -479,39 +479,43 @@ class Email extends Message if (null !== $html) { $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); $html = $htmlPart->getBody(); - - $regexes = [ - ']*src\s*=\s*(?:([\'"])cid:(.+?)\\1|cid:([^>\s]+))', - '<\w+\s+[^>]*background\s*=\s*(?:([\'"])cid:(.+?)\\1|cid:([^>\s]+))', - ]; - $tmpMatches = []; - foreach ($regexes as $regex) { - preg_match_all('/'.$regex.'/i', $html, $tmpMatches); - $names = array_merge($names, $tmpMatches[2], $tmpMatches[3]); - } - $names = array_filter(array_unique($names)); + preg_match_all('(]*src\s*=\s*(?:([\'"])cid:(.+?)\\1|cid:([^>\s]+)))i', $html, $names); + $names = array_filter(array_unique(array_merge($names[2], $names[3]))); } + // usage of reflection is a temporary workaround for missing getters that will be added in 6.2 + $nameRef = new \ReflectionProperty(TextPart::class, 'name'); + $nameRef->setAccessible(true); $otherParts = $relatedParts = []; - foreach ($this->attachments as $part) { + foreach ($this->attachments as $attachment) { + $part = $this->createDataPart($attachment); + if (isset($attachment['part'])) { + $attachment['name'] = $nameRef->getValue($part); + } + + $related = false; foreach ($names as $name) { - if ($name !== $part->getName() && (!$part->hasContentId() || $name !== $part->getContentId())) { + if ($name !== $attachment['name']) { continue; } if (isset($relatedParts[$name])) { continue 2; } - - if ($name !== $part->getContentId()) { - $html = str_replace('cid:'.$name, 'cid:'.$part->getContentId(), $html, $count); + $part->setDisposition('inline'); + $html = str_replace('cid:'.$name, 'cid:'.$part->getContentId(), $html, $count); + if ($count) { + $related = true; } - $relatedParts[$name] = $part; - $part->setName($part->getContentId())->asInline(); + $part->setName($part->getContentId()); - continue 2; + break; } - $otherParts[] = $part; + if ($related) { + $relatedParts[$attachment['name']] = $part; + } else { + $otherParts[] = $part; + } } if (null !== $htmlPart) { $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); @@ -520,6 +524,24 @@ class Email extends Message return [$htmlPart, $otherParts, array_values($relatedParts)]; } + private function createDataPart(array $attachment): DataPart + { + if (isset($attachment['part'])) { + return $attachment['part']; + } + + if (isset($attachment['body'])) { + $part = new DataPart($attachment['body'], $attachment['name'] ?? null, $attachment['content-type'] ?? null); + } else { + $part = DataPart::fromPath($attachment['path'] ?? '', $attachment['name'] ?? null, $attachment['content-type'] ?? null); + } + if ($attachment['inline']) { + $part->asInline(); + } + + return $part; + } + /** * @return $this */ @@ -530,10 +552,7 @@ class Email extends Message return $this; } - /** - * @return $this - */ - private function addListAddressHeaderBody(string $name, array $addresses): static + private function addListAddressHeaderBody(string $name, array $addresses) { if (!$header = $this->getHeaders()->get($name)) { return $this->setListAddressHeaderBody($name, $addresses); @@ -572,6 +591,12 @@ class Email extends Message $this->html = (new TextPart($this->html))->getBody(); } + foreach ($this->attachments as $i => $attachment) { + if (isset($attachment['body']) && \is_resource($attachment['body'])) { + $this->attachments[$i]['body'] = (new TextPart($attachment['body']))->getBody(); + } + } + return [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, parent::__serialize()]; } diff --git a/vendor/symfony/mime/Encoder/QpContentEncoder.php b/vendor/symfony/mime/Encoder/QpContentEncoder.php index 6f420fff3..4703cc2e6 100644 --- a/vendor/symfony/mime/Encoder/QpContentEncoder.php +++ b/vendor/symfony/mime/Encoder/QpContentEncoder.php @@ -46,10 +46,15 @@ final class QpContentEncoder implements ContentEncoderInterface // transform =0D=0A to CRLF $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], ["=09\r\n", "=20\r\n", "\r\n"], $string); - return match (\ord(substr($string, -1))) { - 0x09 => substr_replace($string, '=09', -1), - 0x20 => substr_replace($string, '=20', -1), - default => $string, - }; + switch (\ord(substr($string, -1))) { + case 0x09: + $string = substr_replace($string, '=09', -1); + break; + case 0x20: + $string = substr_replace($string, '=20', -1); + break; + } + + return $string; } } diff --git a/vendor/symfony/mime/Encoder/QpEncoder.php b/vendor/symfony/mime/Encoder/QpEncoder.php index 160dde329..0b4bcf538 100644 --- a/vendor/symfony/mime/Encoder/QpEncoder.php +++ b/vendor/symfony/mime/Encoder/QpEncoder.php @@ -106,6 +106,8 @@ class QpEncoder implements EncoderInterface } /** + * {@inheritdoc} + * * Takes an unencoded string and produces a QP encoded string from it. * * QP encoded strings have a maximum line length of 76 characters. @@ -182,11 +184,12 @@ class QpEncoder implements EncoderInterface private function standardize(string $string): string { $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], ["=09\r\n", "=20\r\n", "\r\n"], $string); + switch ($end = \ord(substr($string, -1))) { + case 0x09: + case 0x20: + $string = substr_replace($string, self::QP_MAP[$end], -1); + } - return match ($end = \ord(substr($string, -1))) { - 0x09, - 0x20 => substr_replace($string, self::QP_MAP[$end], -1), - default => $string, - }; + return $string; } } diff --git a/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php b/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php index 83e2950ce..5d6bee847 100644 --- a/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php +++ b/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php @@ -36,6 +36,9 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface $this->cmd = $cmd; } + /** + * {@inheritdoc} + */ public function isGuesserSupported(): bool { static $supported = null; @@ -55,6 +58,9 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface return $supported = 0 === $exitStatus && '' !== $binPath; } + /** + * {@inheritdoc} + */ public function guessMimeType(string $path): ?string { if (!is_file($path) || !is_readable($path)) { diff --git a/vendor/symfony/mime/FileinfoMimeTypeGuesser.php b/vendor/symfony/mime/FileinfoMimeTypeGuesser.php index aff590115..c40a8196d 100644 --- a/vendor/symfony/mime/FileinfoMimeTypeGuesser.php +++ b/vendor/symfony/mime/FileinfoMimeTypeGuesser.php @@ -24,7 +24,7 @@ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface private ?string $magicFile; /** - * @param string|null $magicFile A magic file to use with the finfo instance + * @param string $magicFile A magic file to use with the finfo instance * * @see http://www.php.net/manual/en/function.finfo-open.php */ @@ -33,11 +33,17 @@ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface $this->magicFile = $magicFile; } + /** + * {@inheritdoc} + */ public function isGuesserSupported(): bool { return \function_exists('finfo_open'); } + /** + * {@inheritdoc} + */ public function guessMimeType(string $path): ?string { if (!is_file($path) || !is_readable($path)) { diff --git a/vendor/symfony/mime/Header/AbstractHeader.php b/vendor/symfony/mime/Header/AbstractHeader.php index 122281127..46e566345 100644 --- a/vendor/symfony/mime/Header/AbstractHeader.php +++ b/vendor/symfony/mime/Header/AbstractHeader.php @@ -34,9 +34,6 @@ abstract class AbstractHeader implements HeaderInterface $this->name = $name; } - /** - * @return void - */ public function setCharset(string $charset) { $this->charset = $charset; @@ -51,8 +48,6 @@ abstract class AbstractHeader implements HeaderInterface * Set the language used in this Header. * * For example, for US English, 'en-us'. - * - * @return void */ public function setLanguage(string $lang) { @@ -69,9 +64,6 @@ abstract class AbstractHeader implements HeaderInterface return $this->name; } - /** - * @return void - */ public function setMaxLineLength(int $lineLength) { $this->lineLength = $lineLength; @@ -239,7 +231,9 @@ abstract class AbstractHeader implements HeaderInterface */ protected function toTokens(string $string = null): array { - $string ??= $this->getBodyAsString(); + if (null === $string) { + $string = $this->getBodyAsString(); + } $tokens = []; // Generate atoms; split at all invisible boundaries followed by WSP @@ -269,8 +263,8 @@ abstract class AbstractHeader implements HeaderInterface // Build all tokens back into compliant header foreach ($tokens as $i => $token) { // Line longer than specified maximum or token was just a new line - if (("\r\n" === $token) - || ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) + if (("\r\n" === $token) || + ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) && '' !== $currentLine) { $headerLines[] = ''; $currentLine = &$headerLines[$lineCount++]; diff --git a/vendor/symfony/mime/Header/DateHeader.php b/vendor/symfony/mime/Header/DateHeader.php index 67156cb79..b07dfedeb 100644 --- a/vendor/symfony/mime/Header/DateHeader.php +++ b/vendor/symfony/mime/Header/DateHeader.php @@ -30,7 +30,7 @@ final class DateHeader extends AbstractHeader /** * @param \DateTimeInterface $body */ - public function setBody(mixed $body): void + public function setBody(mixed $body) { $this->setDateTime($body); } @@ -50,7 +50,7 @@ final class DateHeader extends AbstractHeader * * If a DateTime instance is provided, it is converted to DateTimeImmutable. */ - public function setDateTime(\DateTimeInterface $dateTime): void + public function setDateTime(\DateTimeInterface $dateTime) { if ($dateTime instanceof \DateTime) { $immutable = new \DateTimeImmutable('@'.$dateTime->getTimestamp()); diff --git a/vendor/symfony/mime/Header/HeaderInterface.php b/vendor/symfony/mime/Header/HeaderInterface.php index 5bc4162c3..092fc238a 100644 --- a/vendor/symfony/mime/Header/HeaderInterface.php +++ b/vendor/symfony/mime/Header/HeaderInterface.php @@ -22,8 +22,6 @@ interface HeaderInterface * Sets the body. * * The type depends on the Header concrete class. - * - * @return void */ public function setBody(mixed $body); @@ -34,25 +32,16 @@ interface HeaderInterface */ public function getBody(): mixed; - /** - * @return void - */ public function setCharset(string $charset); public function getCharset(): ?string; - /** - * @return void - */ public function setLanguage(string $lang); public function getLanguage(): ?string; public function getName(): string; - /** - * @return void - */ public function setMaxLineLength(int $lineLength); public function getMaxLineLength(): int; diff --git a/vendor/symfony/mime/Header/Headers.php b/vendor/symfony/mime/Header/Headers.php index 57d730127..115928155 100644 --- a/vendor/symfony/mime/Header/Headers.php +++ b/vendor/symfony/mime/Header/Headers.php @@ -34,8 +34,8 @@ final class Headers 'cc' => MailboxListHeader::class, 'bcc' => MailboxListHeader::class, 'message-id' => IdentificationHeader::class, - 'in-reply-to' => [UnstructuredHeader::class, IdentificationHeader::class], // `In-Reply-To` and `References` are less strict than RFC 2822 (3.6.4) to allow users entering the original email's ... - 'references' => [UnstructuredHeader::class, IdentificationHeader::class], // ... `Message-ID`, even if that is no valid `msg-id` + 'in-reply-to' => UnstructuredHeader::class, // `In-Reply-To` and `References` are less strict than RFC 2822 (3.6.4) to allow users entering the original email's ... + 'references' => UnstructuredHeader::class, // ... `Message-ID`, even if that is no valid `msg-id` 'return-path' => PathHeader::class, ]; @@ -61,7 +61,7 @@ final class Headers } } - public function setMaxLineLength(int $lineLength): void + public function setMaxLineLength(int $lineLength) { $this->lineLength = $lineLength; foreach ($this->all() as $header) { @@ -137,11 +137,7 @@ final class Headers */ public function addHeader(string $name, mixed $argument, array $more = []): static { - $headerClass = self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class; - if (\is_array($headerClass)) { - $headerClass = $headerClass[0]; - } - $parts = explode('\\', $headerClass); + $parts = explode('\\', self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class); $method = 'add'.ucfirst(array_pop($parts)); if ('addUnstructuredHeader' === $method) { $method = 'addTextHeader'; @@ -224,22 +220,10 @@ final class Headers public static function checkHeaderClass(HeaderInterface $header): void { $name = strtolower($header->getName()); - $headerClasses = self::HEADER_CLASS_MAP[$name] ?? []; - if (!\is_array($headerClasses)) { - $headerClasses = [$headerClasses]; - } - if (!$headerClasses) { - return; + if (($c = self::HEADER_CLASS_MAP[$name] ?? null) && !$header instanceof $c) { + throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $c, get_debug_type($header))); } - - foreach ($headerClasses as $c) { - if ($header instanceof $c) { - return; - } - } - - throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), implode('" or "', $headerClasses), get_debug_type($header))); } public function toString(): string @@ -264,7 +248,7 @@ final class Headers return $arr; } - public function getHeaderBody(string $name): mixed + public function getHeaderBody(string $name) { return $this->has($name) ? $this->get($name)->getBody() : null; } diff --git a/vendor/symfony/mime/Header/IdentificationHeader.php b/vendor/symfony/mime/Header/IdentificationHeader.php index 14e18bf25..40fd7c36d 100644 --- a/vendor/symfony/mime/Header/IdentificationHeader.php +++ b/vendor/symfony/mime/Header/IdentificationHeader.php @@ -36,7 +36,7 @@ final class IdentificationHeader extends AbstractHeader * * @throws RfcComplianceException */ - public function setBody(mixed $body): void + public function setBody(mixed $body) { $this->setId($body); } @@ -53,7 +53,7 @@ final class IdentificationHeader extends AbstractHeader * * @throws RfcComplianceException */ - public function setId(string|array $id): void + public function setId(string|array $id) { $this->setIds(\is_array($id) ? $id : [$id]); } @@ -75,7 +75,7 @@ final class IdentificationHeader extends AbstractHeader * * @throws RfcComplianceException */ - public function setIds(array $ids): void + public function setIds(array $ids) { $this->ids = []; $this->idsAsAddresses = []; diff --git a/vendor/symfony/mime/Header/MailboxHeader.php b/vendor/symfony/mime/Header/MailboxHeader.php index 8ba964b53..877e72e35 100644 --- a/vendor/symfony/mime/Header/MailboxHeader.php +++ b/vendor/symfony/mime/Header/MailboxHeader.php @@ -21,7 +21,7 @@ use Symfony\Component\Mime\Exception\RfcComplianceException; */ final class MailboxHeader extends AbstractHeader { - private Address $address; + private $address; public function __construct(string $name, Address $address) { @@ -35,7 +35,7 @@ final class MailboxHeader extends AbstractHeader * * @throws RfcComplianceException */ - public function setBody(mixed $body): void + public function setBody(mixed $body) { $this->setAddress($body); } @@ -51,7 +51,7 @@ final class MailboxHeader extends AbstractHeader /** * @throws RfcComplianceException */ - public function setAddress(Address $address): void + public function setAddress(Address $address) { $this->address = $address; } diff --git a/vendor/symfony/mime/Header/MailboxListHeader.php b/vendor/symfony/mime/Header/MailboxListHeader.php index 8d902fb75..e6e6ce195 100644 --- a/vendor/symfony/mime/Header/MailboxListHeader.php +++ b/vendor/symfony/mime/Header/MailboxListHeader.php @@ -38,15 +38,15 @@ final class MailboxListHeader extends AbstractHeader * * @throws RfcComplianceException */ - public function setBody(mixed $body): void + public function setBody(mixed $body) { $this->setAddresses($body); } /** - * @return Address[] - * * @throws RfcComplianceException + * + * @return Address[] */ public function getBody(): array { @@ -60,7 +60,7 @@ final class MailboxListHeader extends AbstractHeader * * @throws RfcComplianceException */ - public function setAddresses(array $addresses): void + public function setAddresses(array $addresses) { $this->addresses = []; $this->addAddresses($addresses); @@ -73,7 +73,7 @@ final class MailboxListHeader extends AbstractHeader * * @throws RfcComplianceException */ - public function addAddresses(array $addresses): void + public function addAddresses(array $addresses) { foreach ($addresses as $address) { $this->addAddress($address); @@ -83,7 +83,7 @@ final class MailboxListHeader extends AbstractHeader /** * @throws RfcComplianceException */ - public function addAddress(Address $address): void + public function addAddress(Address $address) { $this->addresses[] = $address; } @@ -99,9 +99,9 @@ final class MailboxListHeader extends AbstractHeader /** * Gets the full mailbox list of this Header as an array of valid RFC 2822 strings. * - * @return string[] - * * @throws RfcComplianceException + * + * @return string[] */ public function getAddressStrings(): array { diff --git a/vendor/symfony/mime/Header/ParameterizedHeader.php b/vendor/symfony/mime/Header/ParameterizedHeader.php index 0618e82bd..ac5ccc58e 100644 --- a/vendor/symfony/mime/Header/ParameterizedHeader.php +++ b/vendor/symfony/mime/Header/ParameterizedHeader.php @@ -25,7 +25,7 @@ final class ParameterizedHeader extends UnstructuredHeader */ public const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)'; - private ?Rfc2231Encoder $encoder = null; + private $encoder = null; private array $parameters = []; public function __construct(string $name, string $value, array $parameters = []) @@ -41,7 +41,7 @@ final class ParameterizedHeader extends UnstructuredHeader } } - public function setParameter(string $parameter, ?string $value): void + public function setParameter(string $parameter, ?string $value) { $this->setParameters(array_merge($this->getParameters(), [$parameter => $value])); } @@ -54,7 +54,7 @@ final class ParameterizedHeader extends UnstructuredHeader /** * @param string[] $parameters */ - public function setParameters(array $parameters): void + public function setParameters(array $parameters) { $this->parameters = $parameters; } diff --git a/vendor/symfony/mime/Header/PathHeader.php b/vendor/symfony/mime/Header/PathHeader.php index 63eb30af0..af267bb10 100644 --- a/vendor/symfony/mime/Header/PathHeader.php +++ b/vendor/symfony/mime/Header/PathHeader.php @@ -21,7 +21,7 @@ use Symfony\Component\Mime\Exception\RfcComplianceException; */ final class PathHeader extends AbstractHeader { - private Address $address; + private $address; public function __construct(string $name, Address $address) { @@ -35,7 +35,7 @@ final class PathHeader extends AbstractHeader * * @throws RfcComplianceException */ - public function setBody(mixed $body): void + public function setBody(mixed $body) { $this->setAddress($body); } @@ -45,7 +45,7 @@ final class PathHeader extends AbstractHeader return $this->getAddress(); } - public function setAddress(Address $address): void + public function setAddress(Address $address) { $this->address = $address; } diff --git a/vendor/symfony/mime/Header/UnstructuredHeader.php b/vendor/symfony/mime/Header/UnstructuredHeader.php index 61c06d8f5..668b0be7f 100644 --- a/vendor/symfony/mime/Header/UnstructuredHeader.php +++ b/vendor/symfony/mime/Header/UnstructuredHeader.php @@ -29,8 +29,6 @@ class UnstructuredHeader extends AbstractHeader /** * @param string $body - * - * @return void */ public function setBody(mixed $body) { @@ -52,8 +50,6 @@ class UnstructuredHeader extends AbstractHeader /** * Set the (unencoded) value of this header. - * - * @return void */ public function setValue(string $value) { diff --git a/vendor/symfony/mime/HtmlToTextConverter/DefaultHtmlToTextConverter.php b/vendor/symfony/mime/HtmlToTextConverter/DefaultHtmlToTextConverter.php deleted file mode 100644 index 2aaf8e6c4..000000000 --- a/vendor/symfony/mime/HtmlToTextConverter/DefaultHtmlToTextConverter.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\HtmlToTextConverter; - -/** - * @author Fabien Potencier - */ -class DefaultHtmlToTextConverter implements HtmlToTextConverterInterface -{ - public function convert(string $html, string $charset): string - { - return strip_tags(preg_replace('{<(head|style)\b.*?}is', '', $html)); - } -} diff --git a/vendor/symfony/mime/HtmlToTextConverter/HtmlToTextConverterInterface.php b/vendor/symfony/mime/HtmlToTextConverter/HtmlToTextConverterInterface.php deleted file mode 100644 index 696f37ccf..000000000 --- a/vendor/symfony/mime/HtmlToTextConverter/HtmlToTextConverterInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\HtmlToTextConverter; - -/** - * @author Fabien Potencier - */ -interface HtmlToTextConverterInterface -{ - /** - * Converts an HTML representation of a Message to a text representation. - * - * The output must use the same charset as the HTML one. - */ - public function convert(string $html, string $charset): string; -} diff --git a/vendor/symfony/mime/HtmlToTextConverter/LeagueHtmlToMarkdownConverter.php b/vendor/symfony/mime/HtmlToTextConverter/LeagueHtmlToMarkdownConverter.php deleted file mode 100644 index 253a7b19f..000000000 --- a/vendor/symfony/mime/HtmlToTextConverter/LeagueHtmlToMarkdownConverter.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\HtmlToTextConverter; - -use League\HTMLToMarkdown\HtmlConverter; -use League\HTMLToMarkdown\HtmlConverterInterface; - -/** - * @author Fabien Potencier - */ -class LeagueHtmlToMarkdownConverter implements HtmlToTextConverterInterface -{ - public function __construct( - private HtmlConverterInterface $converter = new HtmlConverter([ - 'hard_break' => true, - 'strip_tags' => true, - 'remove_nodes' => 'head style', - ]), - ) { - } - - public function convert(string $html, string $charset): string - { - return $this->converter->convert($html); - } -} diff --git a/vendor/symfony/mime/LICENSE b/vendor/symfony/mime/LICENSE index 4dd83ce0f..58b42bc8a 100644 --- a/vendor/symfony/mime/LICENSE +++ b/vendor/symfony/mime/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2010-present Fabien Potencier +Copyright (c) 2010-2023 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/mime/Message.php b/vendor/symfony/mime/Message.php index e636c2e8e..a60d0f527 100644 --- a/vendor/symfony/mime/Message.php +++ b/vendor/symfony/mime/Message.php @@ -21,8 +21,8 @@ use Symfony\Component\Mime\Part\TextPart; */ class Message extends RawMessage { - private Headers $headers; - private ?AbstractPart $body; + private $headers; + private $body; public function __construct(Headers $headers = null, AbstractPart $body = null) { @@ -44,9 +44,6 @@ class Message extends RawMessage */ public function setBody(AbstractPart $body = null): static { - if (1 > \func_num_args()) { - trigger_deprecation('symfony/mime', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); - } $this->body = $body; return $this; @@ -125,9 +122,6 @@ class Message extends RawMessage yield from $body->toIterable(); } - /** - * @return void - */ public function ensureValidity() { if (!$this->headers->has('To') && !$this->headers->has('Cc') && !$this->headers->has('Bcc')) { diff --git a/vendor/symfony/mime/MessageConverter.php b/vendor/symfony/mime/MessageConverter.php index bdce921af..0539eac8e 100644 --- a/vendor/symfony/mime/MessageConverter.php +++ b/vendor/symfony/mime/MessageConverter.php @@ -58,7 +58,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))); } - return self::addParts($email, \array_slice($parts, 1)); + 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))); @@ -80,9 +80,9 @@ final class MessageConverter { $parts = $part->getParts(); if ( - 2 === \count($parts) - && $parts[0] instanceof TextPart && 'text' === $parts[0]->getMediaType() && 'plain' === $parts[0]->getMediaSubtype() - && $parts[1] instanceof TextPart && 'text' === $parts[1]->getMediaType() && 'html' === $parts[1]->getMediaSubtype() + 2 === \count($parts) && + $parts[0] instanceof TextPart && 'text' === $parts[0]->getMediaType() && 'plain' === $parts[0]->getMediaSubtype() && + $parts[1] instanceof TextPart && 'text' === $parts[1]->getMediaType() && 'html' === $parts[1]->getMediaSubtype() ) { return (new Email(clone $message->getHeaders())) ->text($parts[0]->getBody(), $parts[0]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8') @@ -104,17 +104,20 @@ 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))); } - return self::addParts($email, \array_slice($parts, 1)); + return self::attachParts($email, \array_slice($parts, 1)); } - private static function addParts(Email $email, array $parts): Email + private static function attachParts(Email $email, array $parts): Email { 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))); } - $email->addPart($part); + $headers = $part->getPreparedHeaders(); + $method = 'inline' === $headers->getHeaderBody('Content-Disposition') ? 'embed' : 'attach'; + $name = $headers->getHeaderParameter('Content-Disposition', 'filename'); + $email->$method($part->getBody(), $name, $part->getMediaType().'/'.$part->getMediaSubtype()); } return $email; diff --git a/vendor/symfony/mime/MimeTypes.php b/vendor/symfony/mime/MimeTypes.php index 21c8aecf2..77cdcc23c 100644 --- a/vendor/symfony/mime/MimeTypes.php +++ b/vendor/symfony/mime/MimeTypes.php @@ -58,14 +58,14 @@ final class MimeTypes implements MimeTypesInterface $this->registerGuesser(new FileinfoMimeTypeGuesser()); } - public static function setDefault(self $default): void + public static function setDefault(self $default) { self::$default = $default; } public static function getDefault(): self { - return self::$default ??= new self(); + return self::$default ?? self::$default = new self(); } /** @@ -73,11 +73,14 @@ final class MimeTypes implements MimeTypesInterface * * The last registered guesser has precedence over the other ones. */ - public function registerGuesser(MimeTypeGuesserInterface $guesser): void + public function registerGuesser(MimeTypeGuesserInterface $guesser) { array_unshift($this->guessers, $guesser); } + /** + * {@inheritdoc} + */ public function getExtensions(string $mimeType): array { if ($this->extensions) { @@ -87,6 +90,9 @@ final class MimeTypes implements MimeTypesInterface return $extensions ?? self::MAP[$mimeType] ?? self::MAP[$lcMimeType ?? strtolower($mimeType)] ?? []; } + /** + * {@inheritdoc} + */ public function getMimeTypes(string $ext): array { if ($this->mimeTypes) { @@ -96,6 +102,9 @@ final class MimeTypes implements MimeTypesInterface return $mimeTypes ?? self::REVERSE_MAP[$ext] ?? self::REVERSE_MAP[$lcExt ?? strtolower($ext)] ?? []; } + /** + * {@inheritdoc} + */ public function isGuesserSupported(): bool { foreach ($this->guessers as $guesser) { @@ -108,6 +117,8 @@ final class MimeTypes implements MimeTypesInterface } /** + * {@inheritdoc} + * * The file is passed to each registered MIME type guesser in reverse order * of their registration (last registered is queried first). Once a guesser * returns a value that is not null, this method terminates and returns the diff --git a/vendor/symfony/mime/Part/AbstractMultipartPart.php b/vendor/symfony/mime/Part/AbstractMultipartPart.php index b7980ea0c..685d25062 100644 --- a/vendor/symfony/mime/Part/AbstractMultipartPart.php +++ b/vendor/symfony/mime/Part/AbstractMultipartPart.php @@ -90,6 +90,10 @@ abstract class AbstractMultipartPart extends AbstractPart private function getBoundary(): string { - return $this->boundary ??= strtr(base64_encode(random_bytes(6)), '+/', '-_'); + if (null === $this->boundary) { + $this->boundary = strtr(base64_encode(random_bytes(6)), '+/', '-_'); + } + + return $this->boundary; } } diff --git a/vendor/symfony/mime/Part/DataPart.php b/vendor/symfony/mime/Part/DataPart.php index b42ecb4da..300772edf 100644 --- a/vendor/symfony/mime/Part/DataPart.php +++ b/vendor/symfony/mime/Part/DataPart.php @@ -13,6 +13,7 @@ namespace Symfony\Component\Mime\Part; use Symfony\Component\Mime\Exception\InvalidArgumentException; use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\MimeTypes; /** * @author Fabien Potencier @@ -22,22 +23,23 @@ class DataPart extends TextPart /** @internal */ protected $_parent; + private static $mimeTypes; + private $filename; private $mediaType; private $cid; + private $handle; /** - * @param resource|string|File $body Use a File instance to defer loading the file until rendering + * @param resource|string $body */ public function __construct($body, string $filename = null, string $contentType = null, string $encoding = null) { unset($this->_parent); - if ($body instanceof File && !$filename) { - $filename = $body->getFilename(); + if (null === $contentType) { + $contentType = 'application/octet-stream'; } - - $contentType ??= $body instanceof File ? $body->getContentType() : 'application/octet-stream'; [$this->mediaType, $subtype] = explode('/', $contentType); parent::__construct($body, null, $subtype, $encoding); @@ -51,7 +53,32 @@ class DataPart extends TextPart public static function fromPath(string $path, string $name = null, string $contentType = null): self { - return new self(new File($path), $name, $contentType); + if (null === $contentType) { + $ext = strtolower(substr($path, strrpos($path, '.') + 1)); + if (null === self::$mimeTypes) { + self::$mimeTypes = new MimeTypes(); + } + $contentType = self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream'; + } + + if ((is_file($path) && !is_readable($path)) || is_dir($path)) { + throw new InvalidArgumentException(sprintf('Path "%s" is not readable.', $path)); + } + + if (false === $handle = @fopen($path, 'r', false)) { + throw new InvalidArgumentException(sprintf('Unable to open path "%s".', $path)); + } + + if (!is_file($path)) { + $cache = fopen('php://temp', 'r+'); + stream_copy_to_stream($handle, $cache); + $handle = $cache; + } + + $p = new self($handle, $name ?: basename($path), $contentType); + $p->handle = $handle; + + return $p; } /** @@ -62,20 +89,6 @@ class DataPart extends TextPart return $this->setDisposition('inline'); } - /** - * @return $this - */ - public function setContentId(string $cid): static - { - if (!str_contains($cid, '@')) { - throw new InvalidArgumentException(sprintf('Invalid cid "%s".', $cid)); - } - - $this->cid = $cid; - - return $this; - } - public function getContentId(): string { return $this->cid ?: $this->cid = $this->generateContentId(); @@ -116,21 +129,18 @@ class DataPart extends TextPart return $str; } - public function getFilename(): ?string - { - return $this->filename; - } - - public function getContentType(): string - { - return implode('/', [$this->getMediaType(), $this->getMediaSubtype()]); - } - private function generateContentId(): string { return bin2hex(random_bytes(16)).'@symfony'; } + public function __destruct() + { + if (null !== $this->handle && \is_resource($this->handle)) { + fclose($this->handle); + } + } + public function __sleep(): array { // converts the body to a string @@ -139,6 +149,7 @@ class DataPart extends TextPart $this->_parent = []; foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) { $r = new \ReflectionProperty(TextPart::class, $name); + $r->setAccessible(true); $this->_parent[$name] = $r->getValue($this); } $this->_headers = $this->getHeaders(); @@ -149,6 +160,7 @@ class DataPart extends TextPart public function __wakeup() { $r = new \ReflectionProperty(AbstractPart::class, 'headers'); + $r->setAccessible(true); $r->setValue($this, $this->_headers); unset($this->_headers); @@ -160,6 +172,7 @@ class DataPart extends TextPart throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } $r = new \ReflectionProperty(TextPart::class, $name); + $r->setAccessible(true); $r->setValue($this, $this->_parent[$name]); } unset($this->_parent); diff --git a/vendor/symfony/mime/Part/File.php b/vendor/symfony/mime/Part/File.php deleted file mode 100644 index 0d75066ea..000000000 --- a/vendor/symfony/mime/Part/File.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part; - -use Symfony\Component\Mime\MimeTypes; - -/** - * @author Fabien Potencier - */ -class File -{ - private static $mimeTypes; - - public function __construct( - private string $path, - private ?string $filename = null, - ) { - } - - public function getPath(): string - { - return $this->path; - } - - public function getContentType(): string - { - $ext = strtolower(pathinfo($this->path, \PATHINFO_EXTENSION)); - self::$mimeTypes ??= new MimeTypes(); - - return self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream'; - } - - public function getSize(): int - { - return filesize($this->path); - } - - public function getFilename(): string - { - return $this->filename ??= basename($this->getPath()); - } -} diff --git a/vendor/symfony/mime/Part/Multipart/FormDataPart.php b/vendor/symfony/mime/Part/Multipart/FormDataPart.php index e7dc3b17b..5f473ed25 100644 --- a/vendor/symfony/mime/Part/Multipart/FormDataPart.php +++ b/vendor/symfony/mime/Part/Multipart/FormDataPart.php @@ -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('The value of the form field "%s" can only be a string, an array, or an instance of TextPart ("%s" given).', $name, 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).', get_debug_type($value))); } $this->fields[$name] = $value; @@ -58,7 +58,7 @@ final class FormDataPart extends AbstractMultipartPart $values = []; $prepare = function ($item, $key, $root = null) use (&$values, &$prepare) { - if (null === $root && \is_int($key) && \is_array($item)) { + if (\is_int($key) && \is_array($item)) { if (1 !== \count($item)) { throw new InvalidArgumentException(sprintf('Form field values with integer keys can only have one array element, the key being the field name and the value being the field value, %d provided.', \count($item))); } @@ -96,7 +96,10 @@ final class FormDataPart extends AbstractMultipartPart { static $r; - $r ??= new \ReflectionProperty(TextPart::class, 'encoding'); + if (null === $r) { + $r = new \ReflectionProperty(TextPart::class, 'encoding'); + $r->setAccessible(true); + } $part->setDisposition('form-data'); $part->setName($name); diff --git a/vendor/symfony/mime/Part/SMimePart.php b/vendor/symfony/mime/Part/SMimePart.php index 7021819f6..29e9dd19e 100644 --- a/vendor/symfony/mime/Part/SMimePart.php +++ b/vendor/symfony/mime/Part/SMimePart.php @@ -107,6 +107,7 @@ class SMimePart extends AbstractPart public function __wakeup(): void { $r = new \ReflectionProperty(AbstractPart::class, 'headers'); + $r->setAccessible(true); $r->setValue($this, $this->_headers); unset($this->_headers); } diff --git a/vendor/symfony/mime/Part/TextPart.php b/vendor/symfony/mime/Part/TextPart.php index 3b1eb8d82..bd73861d5 100644 --- a/vendor/symfony/mime/Part/TextPart.php +++ b/vendor/symfony/mime/Part/TextPart.php @@ -40,7 +40,7 @@ class TextPart extends AbstractPart private $seekable; /** - * @param resource|string|File $body Use a File instance to defer loading the file until rendering + * @param resource|string $body */ public function __construct($body, ?string $charset = 'utf-8', string $subtype = 'plain', string $encoding = null) { @@ -48,15 +48,8 @@ class TextPart extends AbstractPart parent::__construct(); - if (!\is_string($body) && !\is_resource($body) && !$body instanceof File) { - throw new \TypeError(sprintf('The body of "%s" must be a string, a resource, or an instance of "%s" (got "%s").', self::class, File::class, get_debug_type($body))); - } - - if ($body instanceof File) { - $path = $body->getPath(); - if ((is_file($path) && !is_readable($path)) || is_dir($path)) { - throw new InvalidArgumentException(sprintf('Path "%s" is not readable.', $path)); - } + 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))); } $this->body = $body; @@ -96,14 +89,6 @@ class TextPart extends AbstractPart return $this; } - /** - * @return ?string null or one of attachment, inline, or form-data - */ - public function getDisposition(): ?string - { - return $this->disposition; - } - /** * Sets the name of the file (used by FormDataPart). * @@ -116,20 +101,8 @@ class TextPart extends AbstractPart return $this; } - /** - * Gets the name of the file. - */ - public function getName(): ?string - { - return $this->name; - } - public function getBody(): string { - if ($this->body instanceof File) { - return file_get_contents($this->body->getPath()); - } - if (null === $this->seekable) { return $this->body; } @@ -148,14 +121,7 @@ class TextPart extends AbstractPart public function bodyToIterable(): iterable { - if ($this->body instanceof File) { - $path = $this->body->getPath(); - if (false === $handle = @fopen($path, 'r', false)) { - throw new InvalidArgumentException(sprintf('Unable to open path "%s".', $path)); - } - - yield from $this->getEncoder()->encodeByteStream($handle); - } elseif (null !== $this->seekable) { + if (null !== $this->seekable) { if ($this->seekable) { rewind($this->body); } @@ -204,14 +170,14 @@ class TextPart extends AbstractPart private function getEncoder(): ContentEncoderInterface { if ('8bit' === $this->encoding) { - return self::$encoders[$this->encoding] ??= new EightBitContentEncoder(); + return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new EightBitContentEncoder()); } if ('quoted-printable' === $this->encoding) { - return self::$encoders[$this->encoding] ??= new QpContentEncoder(); + return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new QpContentEncoder()); } - return self::$encoders[$this->encoding] ??= new Base64ContentEncoder(); + return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new Base64ContentEncoder()); } private function chooseEncoding(): string @@ -226,7 +192,7 @@ class TextPart extends AbstractPart public function __sleep(): array { // convert resources to strings for serialization - if (null !== $this->seekable || $this->body instanceof File) { + if (null !== $this->seekable) { $this->body = $this->getBody(); $this->seekable = null; } @@ -239,6 +205,7 @@ class TextPart extends AbstractPart public function __wakeup() { $r = new \ReflectionProperty(AbstractPart::class, 'headers'); + $r->setAccessible(true); $r->setValue($this, $this->_headers); unset($this->_headers); } diff --git a/vendor/symfony/mime/RawMessage.php b/vendor/symfony/mime/RawMessage.php index aec398c58..ed051aab6 100644 --- a/vendor/symfony/mime/RawMessage.php +++ b/vendor/symfony/mime/RawMessage.php @@ -54,8 +54,6 @@ class RawMessage } /** - * @return void - * * @throws LogicException if the message is not valid */ public function ensureValidity() diff --git a/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php b/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php index 6ca9cc058..e32e3d951 100644 --- a/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php +++ b/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php @@ -27,6 +27,9 @@ final class EmailAddressContains extends Constraint $this->expectedValue = $expectedValue; } + /** + * {@inheritdoc} + */ public function toString(): string { return sprintf('contains address "%s" with value "%s"', $this->headerName, $this->expectedValue); @@ -34,10 +37,12 @@ final class EmailAddressContains extends Constraint /** * @param RawMessage $message + * + * {@inheritdoc} */ protected function matches($message): bool { - if (RawMessage::class === $message::class) { + if (RawMessage::class === \get_class($message)) { throw new \LogicException('Unable to test a message address on a RawMessage instance.'); } @@ -59,6 +64,8 @@ final class EmailAddressContains extends Constraint /** * @param RawMessage $message + * + * {@inheritdoc} */ protected function failureDescription($message): string { diff --git a/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php b/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php index d5c8ae981..a0ee81ddd 100644 --- a/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php +++ b/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php @@ -26,6 +26,9 @@ final class EmailAttachmentCount extends Constraint $this->transport = $transport; } + /** + * {@inheritdoc} + */ public function toString(): string { return sprintf('has sent "%d" attachment(s)', $this->expectedValue); @@ -33,10 +36,12 @@ final class EmailAttachmentCount extends Constraint /** * @param RawMessage $message + * + * {@inheritdoc} */ protected function matches($message): bool { - if (RawMessage::class === $message::class || Message::class === $message::class) { + if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { throw new \LogicException('Unable to test a message attachment on a RawMessage or Message instance.'); } @@ -45,6 +50,8 @@ final class EmailAttachmentCount extends Constraint /** * @param RawMessage $message + * + * {@inheritdoc} */ protected function failureDescription($message): string { diff --git a/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php b/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php index b7c5625b2..ef4a28585 100644 --- a/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php +++ b/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php @@ -23,6 +23,9 @@ final class EmailHasHeader extends Constraint $this->headerName = $headerName; } + /** + * {@inheritdoc} + */ public function toString(): string { return sprintf('has header "%s"', $this->headerName); @@ -30,10 +33,12 @@ final class EmailHasHeader extends Constraint /** * @param RawMessage $message + * + * {@inheritdoc} */ protected function matches($message): bool { - if (RawMessage::class === $message::class) { + if (RawMessage::class === \get_class($message)) { throw new \LogicException('Unable to test a message header on a RawMessage instance.'); } @@ -42,6 +47,8 @@ final class EmailHasHeader extends Constraint /** * @param RawMessage $message + * + * {@inheritdoc} */ protected function failureDescription($message): string { diff --git a/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php b/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php index edb6ab425..bb0cba698 100644 --- a/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php +++ b/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php @@ -26,6 +26,9 @@ final class EmailHeaderSame extends Constraint $this->expectedValue = $expectedValue; } + /** + * {@inheritdoc} + */ public function toString(): string { return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); @@ -33,10 +36,12 @@ final class EmailHeaderSame extends Constraint /** * @param RawMessage $message + * + * {@inheritdoc} */ protected function matches($message): bool { - if (RawMessage::class === $message::class) { + if (RawMessage::class === \get_class($message)) { throw new \LogicException('Unable to test a message header on a RawMessage instance.'); } @@ -45,6 +50,8 @@ final class EmailHeaderSame extends Constraint /** * @param RawMessage $message + * + * {@inheritdoc} */ protected function failureDescription($message): string { diff --git a/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php b/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php index cbf303d1b..67ab85eb6 100644 --- a/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php +++ b/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php @@ -24,24 +24,31 @@ final class EmailHtmlBodyContains extends Constraint $this->expectedText = $expectedText; } + /** + * {@inheritdoc} + */ public function toString(): string { return sprintf('contains "%s"', $this->expectedText); } /** + * {@inheritdoc} + * * @param RawMessage $message */ protected function matches($message): bool { - if (RawMessage::class === $message::class || Message::class === $message::class) { + if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { throw new \LogicException('Unable to test a message HTML body on a RawMessage or Message instance.'); } - return str_contains($message->getHtmlBody(), $this->expectedText); + return false !== mb_strpos($message->getHtmlBody(), $this->expectedText); } /** + * {@inheritdoc} + * * @param RawMessage $message */ protected function failureDescription($message): string diff --git a/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php b/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php index 592595cf4..f31655fd0 100644 --- a/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php +++ b/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php @@ -24,24 +24,31 @@ final class EmailTextBodyContains extends Constraint $this->expectedText = $expectedText; } + /** + * {@inheritdoc} + */ public function toString(): string { return sprintf('contains "%s"', $this->expectedText); } /** + * {@inheritdoc} + * * @param RawMessage $message */ protected function matches($message): bool { - if (RawMessage::class === $message::class || Message::class === $message::class) { + if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { throw new \LogicException('Unable to test a message text body on a RawMessage or Message instance.'); } - return str_contains($message->getTextBody(), $this->expectedText); + return false !== mb_strpos($message->getTextBody(), $this->expectedText); } /** + * {@inheritdoc} + * * @param RawMessage $message */ protected function failureDescription($message): string diff --git a/vendor/symfony/mime/composer.json b/vendor/symfony/mime/composer.json index adaf43852..02e3a07f0 100644 --- a/vendor/symfony/mime/composer.json +++ b/vendor/symfony/mime/composer.json @@ -16,25 +16,24 @@ } ], "require": { - "php": ">=8.1", + "php": ">=8.0.2", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", - "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/property-access": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "^6.2" + "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" }, "conflict": { "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<5.4", - "symfony/serializer": "<6.2" + "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" }, "autoload": { "psr-4": { "Symfony\\Component\\Mime\\": "" }, diff --git a/vendor/symfony/var-exporter/CHANGELOG.md b/vendor/symfony/var-exporter/CHANGELOG.md index 1b21a0bbd..3406c30ef 100644 --- a/vendor/symfony/var-exporter/CHANGELOG.md +++ b/vendor/symfony/var-exporter/CHANGELOG.md @@ -1,14 +1,6 @@ CHANGELOG ========= -6.2 ---- - - * Add support for lazy ghost objects and virtual proxies - * Add `Hydrator::hydrate()` - * Preserve PHP references also when using `Hydrator::hydrate()` or `Instantiator::instantiate()` - * Add support for hydrating from native (array) casts - 5.1.0 ----- diff --git a/vendor/symfony/var-exporter/Exception/LogicException.php b/vendor/symfony/var-exporter/Exception/LogicException.php deleted file mode 100644 index 619d0559a..000000000 --- a/vendor/symfony/var-exporter/Exception/LogicException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Exception; - -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/var-exporter/Hydrator.php b/vendor/symfony/var-exporter/Hydrator.php deleted file mode 100644 index 5f456fb3c..000000000 --- a/vendor/symfony/var-exporter/Hydrator.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Internal\Hydrator as InternalHydrator; - -/** - * Utility class to hydrate the properties of an object. - * - * @author Nicolas Grekas - */ -final class Hydrator -{ - /** - * Sets the properties of an object, including private and protected ones. - * - * For example: - * - * // Sets the public or protected $object->propertyName property - * Hydrator::hydrate($object, ['propertyName' => $propertyValue]); - * - * // Sets a private property defined on its parent Bar class: - * Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]); - * - * // Alternative way to set the private $object->privateBarProperty property - * Hydrator::hydrate($object, [], [ - * Bar::class => ['privateBarProperty' => $propertyValue], - * ]); - * - * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be hydrated - * by using the special "\0" property name to define their internal value: - * - * // Hydrates an SplObjectStorage where $info1 is attached to $obj1, etc. - * Hydrator::hydrate($object, ["\0" => [$obj1, $info1, $obj2, $info2...]]); - * - * // Hydrates an ArrayObject populated with $inputArray - * Hydrator::hydrate($object, ["\0" => [$inputArray]]); - * - * @template T of object - * - * @param T $instance The object to hydrate - * @param array $properties The properties to set on the instance - * @param array> $scopedProperties The properties to set on the instance, - * keyed by their declaring class - * - * @return T - */ - public static function hydrate(object $instance, array $properties = [], array $scopedProperties = []): object - { - if ($properties) { - $class = $instance::class; - $propertyScopes = InternalHydrator::$propertyScopes[$class] ??= InternalHydrator::getPropertyScopes($class); - - foreach ($properties as $name => &$value) { - [$scope, $name, $readonlyScope] = $propertyScopes[$name] ?? [$class, $name, $class]; - $scopedProperties[$readonlyScope ?? $scope][$name] = &$value; - } - unset($value); - } - - foreach ($scopedProperties as $scope => $properties) { - if ($properties) { - (InternalHydrator::$simpleHydrators[$scope] ??= InternalHydrator::getSimpleHydrator($scope))($properties, $instance); - } - } - - return $instance; - } -} diff --git a/vendor/symfony/var-exporter/Instantiator.php b/vendor/symfony/var-exporter/Instantiator.php index 10200c00b..38fce27b6 100644 --- a/vendor/symfony/var-exporter/Instantiator.php +++ b/vendor/symfony/var-exporter/Instantiator.php @@ -13,6 +13,7 @@ namespace Symfony\Component\VarExporter; use Symfony\Component\VarExporter\Exception\ExceptionInterface; use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; +use Symfony\Component\VarExporter\Internal\Hydrator; use Symfony\Component\VarExporter\Internal\Registry; /** @@ -25,35 +26,67 @@ final class Instantiator /** * Creates an object and sets its properties without calling its constructor nor any other methods. * - * @see Hydrator::hydrate() for examples + * For example: * - * @template T of object + * // creates an empty instance of Foo + * Instantiator::instantiate(Foo::class); * - * @param class-string $class The class of the instance to create - * @param array $properties The properties to set on the instance - * @param array> $scopedProperties The properties to set on the instance, - * keyed by their declaring class + * // creates a Foo instance and sets one of its properties + * Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]); * - * @return T + * // creates a Foo instance and sets a private property defined on its parent Bar class + * Instantiator::instantiate(Foo::class, [], [ + * Bar::class => ['privateBarProperty' => $propertyValue], + * ]); + * + * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be created + * by using the special "\0" property name to define their internal value: + * + * // creates an SplObjectStorage where $info1 is attached to $obj1, etc. + * Instantiator::instantiate(SplObjectStorage::class, ["\0" => [$obj1, $info1, $obj2, $info2...]]); + * + * // creates an ArrayObject populated with $inputArray + * Instantiator::instantiate(ArrayObject::class, ["\0" => [$inputArray]]); + * + * @param string $class The class of the instance to create + * @param array $properties The properties to set on the instance + * @param array $privateProperties The private properties to set on the instance, + * keyed by their declaring class * * @throws ExceptionInterface When the instance cannot be created */ - public static function instantiate(string $class, array $properties = [], array $scopedProperties = []): object + public static function instantiate(string $class, array $properties = [], array $privateProperties = []): object { - $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class); + $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); if (Registry::$cloneable[$class]) { - $instance = clone Registry::$prototypes[$class]; + $wrappedInstance = [clone Registry::$prototypes[$class]]; } elseif (Registry::$instantiableWithoutConstructor[$class]) { - $instance = $reflector->newInstanceWithoutConstructor(); + $wrappedInstance = [$reflector->newInstanceWithoutConstructor()]; } elseif (null === Registry::$prototypes[$class]) { throw new NotInstantiableTypeException($class); } elseif ($reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize')) { - $instance = unserialize('C:'.\strlen($class).':"'.$class.'":0:{}'); + $wrappedInstance = [unserialize('C:'.\strlen($class).':"'.$class.'":0:{}')]; } else { - $instance = unserialize('O:'.\strlen($class).':"'.$class.'":0:{}'); + $wrappedInstance = [unserialize('O:'.\strlen($class).':"'.$class.'":0:{}')]; } - return $properties || $scopedProperties ? Hydrator::hydrate($instance, $properties, $scopedProperties) : $instance; + if ($properties) { + $privateProperties[$class] = isset($privateProperties[$class]) ? $properties + $privateProperties[$class] : $properties; + } + + foreach ($privateProperties as $class => $properties) { + if (!$properties) { + continue; + } + foreach ($properties as $name => $value) { + // because they're also used for "unserialization", hydrators + // deal with array of instances, so we need to wrap values + $properties[$name] = [$value]; + } + (Hydrator::$hydrators[$class] ?? Hydrator::getHydrator($class))($properties, $wrappedInstance); + } + + return $wrappedInstance[0]; } } diff --git a/vendor/symfony/var-exporter/Internal/Exporter.php b/vendor/symfony/var-exporter/Internal/Exporter.php index ae12ec414..6ee3ee7f4 100644 --- a/vendor/symfony/var-exporter/Internal/Exporter.php +++ b/vendor/symfony/var-exporter/Internal/Exporter.php @@ -31,11 +31,9 @@ class Exporter * @param int &$objectsCount * @param bool &$valuesAreStatic * - * @return array - * * @throws NotInstantiableTypeException When a value cannot be serialized */ - public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic) + public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic): array { $refs = $values; foreach ($values as $k => $value) { @@ -73,8 +71,8 @@ class Exporter goto handle_value; } - $class = $value::class; - $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class); + $class = \get_class($value); + $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); if ($reflector->hasMethod('__serialize')) { if (!$reflector->getMethod('__serialize')->isPublic()) { @@ -135,7 +133,7 @@ class Exporter $i = 0; $n = (string) $name; if ('' === $n || "\0" !== $n[0]) { - $c = $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass'; + $c = \PHP_VERSION_ID >= 80100 && $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass'; } elseif ('*' === $n[1]) { $n = substr($n, 3); $c = $reflector->getProperty($n)->class; @@ -191,7 +189,7 @@ class Exporter return $values; } - public static function export($value, $indent = '') + public static function export($value, string $indent = '') { switch (true) { case \is_int($value) || \is_float($value): return var_export($value, true); @@ -230,7 +228,7 @@ class Exporter return substr($m[1], 0, -2); } - if (str_ends_with($m[1], 'n".\'')) { + if ('n".\'' === substr($m[1], -4)) { return substr_replace($m[1], "\n".$subIndent.".'".$m[2], -2); } @@ -368,7 +366,7 @@ class Exporter self::export($value->wakeups, $subIndent), ]; - return '\\'.$value::class."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')'; + return '\\'.\get_class($value)."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')'; } /** @@ -378,7 +376,7 @@ class Exporter private static function getArrayObjectProperties($value, $proto): array { $reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject'; - $reflector = Registry::$reflectors[$reflector] ??= Registry::getClassReflector($reflector); + $reflector = Registry::$reflectors[$reflector] ?? Registry::getClassReflector($reflector); $properties = [ $arrayValue = (array) $value, diff --git a/vendor/symfony/var-exporter/Internal/Hydrator.php b/vendor/symfony/var-exporter/Internal/Hydrator.php index f665f6ee1..5ed6bdc94 100644 --- a/vendor/symfony/var-exporter/Internal/Hydrator.php +++ b/vendor/symfony/var-exporter/Internal/Hydrator.php @@ -21,8 +21,6 @@ use Symfony\Component\VarExporter\Exception\ClassNotFoundException; class Hydrator { public static $hydrators = []; - public static $simpleHydrators = []; - public static $propertyScopes = []; public $registry; public $values; @@ -42,7 +40,7 @@ class Hydrator public static function hydrate($objects, $values, $properties, $value, $wakeups) { foreach ($properties as $class => $vars) { - (self::$hydrators[$class] ??= self::getHydrator($class))($vars, $objects); + (self::$hydrators[$class] ?? self::getHydrator($class))($vars, $objects); } foreach ($wakeups as $k => $v) { if (\is_array($v)) { @@ -57,28 +55,26 @@ class Hydrator public static function getHydrator($class) { - $baseHydrator = self::$hydrators['stdClass'] ??= static function ($properties, $objects) { - foreach ($properties as $name => $values) { - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - }; - switch ($class) { case 'stdClass': - return $baseHydrator; + return self::$hydrators[$class] = static function ($properties, $objects) { + foreach ($properties as $name => $values) { + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + }; case 'ErrorException': - return $baseHydrator->bindTo(null, new class() extends \ErrorException { + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \ErrorException { }); case 'TypeError': - return $baseHydrator->bindTo(null, new class() extends \Error { + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \Error { }); case 'SplObjectStorage': - return static function ($properties, $objects) { + return self::$hydrators[$class] = static function ($properties, $objects) { foreach ($properties as $name => $values) { if ("\0" === $name) { foreach ($values as $i => $v) { @@ -103,9 +99,9 @@ class Hydrator switch ($class) { case 'ArrayIterator': case 'ArrayObject': - $constructor = $classReflector->getConstructor()->invokeArgs(...); + $constructor = \Closure::fromCallable([$classReflector->getConstructor(), 'invokeArgs']); - return static function ($properties, $objects) use ($constructor) { + return self::$hydrators[$class] = static function ($properties, $objects) use ($constructor) { foreach ($properties as $name => $values) { if ("\0" !== $name) { foreach ($values as $i => $v) { @@ -120,25 +116,26 @@ class Hydrator } if (!$classReflector->isInternal()) { - return $baseHydrator->bindTo(null, $class); + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, $class); } if ($classReflector->name !== $class) { - return self::$hydrators[$classReflector->name] ??= self::getHydrator($classReflector->name); + return self::$hydrators[$classReflector->name] ?? self::getHydrator($classReflector->name); } $propertySetters = []; foreach ($classReflector->getProperties() as $propertyReflector) { if (!$propertyReflector->isStatic()) { - $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...); + $propertyReflector->setAccessible(true); + $propertySetters[$propertyReflector->name] = \Closure::fromCallable([$propertyReflector, 'setValue']); } } if (!$propertySetters) { - return $baseHydrator; + return self::$hydrators[$class] = self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'); } - return static function ($properties, $objects) use ($propertySetters) { + return self::$hydrators[$class] = static function ($properties, $objects) use ($propertySetters) { foreach ($properties as $name => $values) { if ($setValue = $propertySetters[$name] ?? null) { foreach ($values as $i => $v) { @@ -152,148 +149,4 @@ class Hydrator } }; } - - public static function getSimpleHydrator($class) - { - $baseHydrator = self::$simpleHydrators['stdClass'] ??= (function ($properties, $object) { - $readonly = (array) $this; - - foreach ($properties as $name => &$value) { - $object->$name = $value; - - if (!($readonly[$name] ?? false)) { - $object->$name = &$value; - } - } - })->bindTo(new \stdClass()); - - switch ($class) { - case 'stdClass': - return $baseHydrator; - - case 'ErrorException': - return $baseHydrator->bindTo(new \stdClass(), new class() extends \ErrorException { - }); - - case 'TypeError': - return $baseHydrator->bindTo(new \stdClass(), new class() extends \Error { - }); - - case 'SplObjectStorage': - return static function ($properties, $object) { - foreach ($properties as $name => &$value) { - if ("\0" !== $name) { - $object->$name = $value; - $object->$name = &$value; - continue; - } - for ($i = 0; $i < \count($value); ++$i) { - $object->attach($value[$i], $value[++$i]); - } - } - }; - } - - if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) { - throw new ClassNotFoundException($class); - } - $classReflector = new \ReflectionClass($class); - - switch ($class) { - case 'ArrayIterator': - case 'ArrayObject': - $constructor = $classReflector->getConstructor()->invokeArgs(...); - - return static function ($properties, $object) use ($constructor) { - foreach ($properties as $name => &$value) { - if ("\0" === $name) { - $constructor($object, $value); - } else { - $object->$name = $value; - $object->$name = &$value; - } - } - }; - } - - if (!$classReflector->isInternal()) { - $readonly = new \stdClass(); - foreach ($classReflector->getProperties(\ReflectionProperty::IS_READONLY) as $propertyReflector) { - if ($class === $propertyReflector->class) { - $readonly->{$propertyReflector->name} = true; - } - } - - return $baseHydrator->bindTo($readonly, $class); - } - - if ($classReflector->name !== $class) { - return self::$simpleHydrators[$classReflector->name] ??= self::getSimpleHydrator($classReflector->name); - } - - $propertySetters = []; - foreach ($classReflector->getProperties() as $propertyReflector) { - if (!$propertyReflector->isStatic()) { - $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...); - } - } - - if (!$propertySetters) { - return $baseHydrator; - } - - return static function ($properties, $object) use ($propertySetters) { - foreach ($properties as $name => &$value) { - if ($setValue = $propertySetters[$name] ?? null) { - $setValue($object, $value); - } else { - $object->$name = $value; - $object->$name = &$value; - } - } - }; - } - - /** - * @return array - */ - public static function getPropertyScopes($class) - { - $propertyScopes = []; - $r = new \ReflectionClass($class); - - foreach ($r->getProperties() as $property) { - $flags = $property->getModifiers(); - - if (\ReflectionProperty::IS_STATIC & $flags) { - continue; - } - $name = $property->name; - - if (\ReflectionProperty::IS_PRIVATE & $flags) { - $propertyScopes["\0$class\0$name"] = $propertyScopes[$name] = [$class, $name, $flags & \ReflectionProperty::IS_READONLY ? $class : null]; - continue; - } - $propertyScopes[$name] = [$class, $name, $flags & \ReflectionProperty::IS_READONLY ? $property->class : null]; - - if (\ReflectionProperty::IS_PROTECTED & $flags) { - $propertyScopes["\0*\0$name"] = $propertyScopes[$name]; - } - } - - while ($r = $r->getParentClass()) { - $class = $r->name; - - foreach ($r->getProperties(\ReflectionProperty::IS_PRIVATE) as $property) { - if (!$property->isStatic()) { - $name = $property->name; - $readonlyScope = $property->isReadOnly() ? $class : null; - $propertyScopes["\0$class\0$name"] = [$class, $name, $readonlyScope]; - $propertyScopes[$name] ??= [$class, $name, $readonlyScope]; - } - } - } - - return $propertyScopes; - } } diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php b/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php deleted file mode 100644 index baffe9bfb..000000000 --- a/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php +++ /dev/null @@ -1,146 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -/** - * Stores the state of lazy objects and caches related reflection information. - * - * As a micro-optimization, this class uses no type declarations. - * - * @internal - */ -class LazyObjectRegistry -{ - /** - * @var array - */ - public static $classReflectors = []; - - /** - * @var array> - */ - public static $defaultProperties = []; - - /** - * @var array> - */ - public static $classResetters = []; - - /** - * @var array - */ - public static $classAccessors = []; - - /** - * @var array - */ - public static $parentMethods = []; - - public static ?\Closure $noInitializerState = null; - - public static function getClassResetters($class) - { - $classProperties = []; - - if ((self::$classReflectors[$class] ??= new \ReflectionClass($class))->isInternal()) { - $propertyScopes = []; - } else { - $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); - } - - foreach ($propertyScopes as $key => [$scope, $name, $readonlyScope]) { - $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name; - - if ($k === $key && "\0$class\0lazyObjectState" !== $k) { - $classProperties[$readonlyScope ?? $scope][$name] = $key; - } - } - - $resetters = []; - foreach ($classProperties as $scope => $properties) { - $resetters[] = \Closure::bind(static function ($instance, $skippedProperties, $onlyProperties = null) use ($properties) { - foreach ($properties as $name => $key) { - if (!\array_key_exists($key, $skippedProperties) && (null === $onlyProperties || \array_key_exists($key, $onlyProperties))) { - unset($instance->$name); - } - } - }, null, $scope); - } - - $resetters[] = static function ($instance, $skippedProperties, $onlyProperties = null) { - foreach ((array) $instance as $name => $value) { - if ("\0" !== ($name[0] ?? '') && !\array_key_exists($name, $skippedProperties) && (null === $onlyProperties || \array_key_exists($name, $onlyProperties))) { - unset($instance->$name); - } - } - }; - - return $resetters; - } - - public static function getClassAccessors($class) - { - return \Closure::bind(static fn () => [ - 'get' => static function &($instance, $name, $readonly) { - if (!$readonly) { - return $instance->$name; - } - $value = $instance->$name; - - return $value; - }, - 'set' => static function ($instance, $name, $value) { - $instance->$name = $value; - }, - 'isset' => static fn ($instance, $name) => isset($instance->$name), - 'unset' => static function ($instance, $name) { - unset($instance->$name); - }, - ], null, \Closure::class === $class ? null : $class)(); - } - - public static function getParentMethods($class) - { - $parent = get_parent_class($class); - $methods = []; - - foreach (['set', 'isset', 'unset', 'clone', 'serialize', 'unserialize', 'sleep', 'wakeup', 'destruct', 'get'] as $method) { - if (!$parent || !method_exists($parent, '__'.$method)) { - $methods[$method] = false; - } else { - $m = new \ReflectionMethod($parent, '__'.$method); - $methods[$method] = !$m->isAbstract() && !$m->isPrivate(); - } - } - - $methods['get'] = $methods['get'] ? ($m->returnsReference() ? 2 : 1) : 0; - - return $methods; - } - - public static function getScope($propertyScopes, $class, $property, $readonlyScope = null) - { - if (null === $readonlyScope && !isset($propertyScopes[$k = "\0$class\0$property"]) && !isset($propertyScopes[$k = "\0*\0$property"])) { - return null; - } - $frame = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]; - - if (\ReflectionProperty::class === $scope = $frame['class'] ?? \Closure::class) { - $scope = $frame['object']->class; - } - if (null === $readonlyScope && '*' === $k[1] && ($class === $scope || is_subclass_of($class, $scope))) { - return null; - } - - return $scope; - } -} diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectState.php b/vendor/symfony/var-exporter/Internal/LazyObjectState.php deleted file mode 100644 index 2f649dd1c..000000000 --- a/vendor/symfony/var-exporter/Internal/LazyObjectState.php +++ /dev/null @@ -1,130 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -use Symfony\Component\VarExporter\Hydrator as PublicHydrator; - -/** - * Keeps the state of lazy objects. - * - * As a micro-optimization, this class uses no type declarations. - * - * @internal - */ -class LazyObjectState -{ - public const STATUS_UNINITIALIZED_FULL = 1; - public const STATUS_UNINITIALIZED_PARTIAL = 2; - public const STATUS_INITIALIZED_FULL = 3; - public const STATUS_INITIALIZED_PARTIAL = 4; - - /** - * @var array - */ - public readonly array $skippedProperties; - - /** - * @var self::STATUS_* - */ - public int $status = 0; - - public object $realInstance; - - public function __construct(public readonly \Closure|array $initializer, $skippedProperties = []) - { - $this->skippedProperties = $skippedProperties; - $this->status = \is_array($initializer) ? self::STATUS_UNINITIALIZED_PARTIAL : self::STATUS_UNINITIALIZED_FULL; - } - - public function initialize($instance, $propertyName, $propertyScope) - { - if (self::STATUS_INITIALIZED_FULL === $this->status) { - return self::STATUS_INITIALIZED_FULL; - } - - if (\is_array($this->initializer)) { - $class = $instance::class; - $propertyScope ??= $class; - $propertyScopes = Hydrator::$propertyScopes[$class]; - $propertyScopes[$k = "\0$propertyScope\0$propertyName"] ?? $propertyScopes[$k = "\0*\0$propertyName"] ?? $k = $propertyName; - - if ($initializer = $this->initializer[$k] ?? null) { - $value = $initializer(...[$instance, $propertyName, $propertyScope, LazyObjectRegistry::$defaultProperties[$class][$k] ?? null]); - $accessor = LazyObjectRegistry::$classAccessors[$propertyScope] ??= LazyObjectRegistry::getClassAccessors($propertyScope); - $accessor['set']($instance, $propertyName, $value); - - return $this->status = self::STATUS_INITIALIZED_PARTIAL; - } - - $status = self::STATUS_UNINITIALIZED_PARTIAL; - - if ($initializer = $this->initializer["\0"] ?? null) { - if (!\is_array($values = $initializer($instance, LazyObjectRegistry::$defaultProperties[$class]))) { - throw new \TypeError(sprintf('The lazy-initializer defined for instance of "%s" must return an array, got "%s".', $class, get_debug_type($values))); - } - $properties = (array) $instance; - foreach ($values as $key => $value) { - if ($k === $key) { - $status = self::STATUS_INITIALIZED_PARTIAL; - } - if (!\array_key_exists($key, $properties) && [$scope, $name, $readonlyScope] = $propertyScopes[$key] ?? null) { - $scope = $readonlyScope ?? ('*' !== $scope ? $scope : $class); - $accessor = LazyObjectRegistry::$classAccessors[$scope] ??= LazyObjectRegistry::getClassAccessors($scope); - $accessor['set']($instance, $name, $value); - } - } - } - - return $status; - } - - $this->status = self::STATUS_INITIALIZED_FULL; - - try { - if ($defaultProperties = array_diff_key(LazyObjectRegistry::$defaultProperties[$instance::class], $this->skippedProperties)) { - PublicHydrator::hydrate($instance, $defaultProperties); - } - - ($this->initializer)($instance); - } catch (\Throwable $e) { - $this->status = self::STATUS_UNINITIALIZED_FULL; - $this->reset($instance); - - throw $e; - } - - return self::STATUS_INITIALIZED_FULL; - } - - public function reset($instance): void - { - $class = $instance::class; - $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); - $skippedProperties = $this->skippedProperties; - $properties = (array) $instance; - $onlyProperties = \is_array($this->initializer) ? $this->initializer : null; - - foreach ($propertyScopes as $key => [$scope, $name, $readonlyScope]) { - $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name; - - if ($k === $key && (null !== $readonlyScope || !\array_key_exists($k, $properties))) { - $skippedProperties[$k] = true; - } - } - - foreach (LazyObjectRegistry::$classResetters[$class] as $reset) { - $reset($instance, $skippedProperties, $onlyProperties); - } - - $this->status = self::STATUS_INITIALIZED_FULL === $this->status ? self::STATUS_UNINITIALIZED_FULL : self::STATUS_UNINITIALIZED_PARTIAL; - } -} diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php b/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php deleted file mode 100644 index cccdf6cff..000000000 --- a/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -if (\PHP_VERSION_ID >= 80300) { - /** - * @internal - */ - trait LazyObjectTrait - { - private readonly LazyObjectState $lazyObjectState; - } -} else { - /** - * @internal - */ - trait LazyObjectTrait - { - private LazyObjectState $lazyObjectState; - } -} diff --git a/vendor/symfony/var-exporter/Internal/Registry.php b/vendor/symfony/var-exporter/Internal/Registry.php index 09d2de2a0..a9fb06146 100644 --- a/vendor/symfony/var-exporter/Internal/Registry.php +++ b/vendor/symfony/var-exporter/Internal/Registry.php @@ -58,9 +58,9 @@ class Registry public static function f($class) { - $reflector = self::$reflectors[$class] ??= self::getClassReflector($class, true, false); + $reflector = self::$reflectors[$class] ?? self::getClassReflector($class, true, false); - return self::$factories[$class] = [$reflector, 'newInstanceWithoutConstructor'](...); + return self::$factories[$class] = \Closure::fromCallable([$reflector, 'newInstanceWithoutConstructor']); } public static function getClassReflector($class, $instantiableWithoutConstructor = false, $cloneable = null) @@ -75,17 +75,17 @@ class Registry } elseif (!$isClass || $reflector->isAbstract()) { throw new NotInstantiableTypeException($class); } elseif ($reflector->name !== $class) { - $reflector = self::$reflectors[$name = $reflector->name] ??= self::getClassReflector($name, false, $cloneable); + $reflector = self::$reflectors[$name = $reflector->name] ?? self::getClassReflector($name, false, $cloneable); self::$cloneable[$class] = self::$cloneable[$name]; self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name]; self::$prototypes[$class] = self::$prototypes[$name]; - return $reflector; + return self::$reflectors[$class] = $reflector; } else { try { $proto = $reflector->newInstanceWithoutConstructor(); $instantiableWithoutConstructor = true; - } catch (\ReflectionException) { + } catch (\ReflectionException $e) { $proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:'; if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) { $proto = null; @@ -132,13 +132,15 @@ class Registry new \ReflectionProperty(\Error::class, 'trace'), new \ReflectionProperty(\Exception::class, 'trace'), ]; - $setTrace[0] = $setTrace[0]->setValue(...); - $setTrace[1] = $setTrace[1]->setValue(...); + $setTrace[0]->setAccessible(true); + $setTrace[1]->setAccessible(true); + $setTrace[0] = \Closure::fromCallable([$setTrace[0], 'setValue']); + $setTrace[1] = \Closure::fromCallable([$setTrace[1], 'setValue']); } $setTrace[$proto instanceof \Exception]($proto, []); } - return $reflector; + return self::$reflectors[$class] = $reflector; } } diff --git a/vendor/symfony/var-exporter/LICENSE b/vendor/symfony/var-exporter/LICENSE index 7536caeae..99757d517 100644 --- a/vendor/symfony/var-exporter/LICENSE +++ b/vendor/symfony/var-exporter/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018-present Fabien Potencier +Copyright (c) 2018-2023 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/var-exporter/LazyGhostTrait.php b/vendor/symfony/var-exporter/LazyGhostTrait.php deleted file mode 100644 index 13e33f59c..000000000 --- a/vendor/symfony/var-exporter/LazyGhostTrait.php +++ /dev/null @@ -1,391 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry; -use Symfony\Component\VarExporter\Internal\LazyObjectState; -use Symfony\Component\VarExporter\Internal\LazyObjectTrait; - -trait LazyGhostTrait -{ - use LazyObjectTrait; - - /** - * Creates a lazy-loading ghost instance. - * - * When the initializer is a closure, it should initialize all properties at - * once and is given the instance to initialize as argument. - * - * When the initializer is an array of closures, it should be indexed by - * properties and closures should accept 4 arguments: the instance to - * initialize, the property to initialize, its write-scope, and its default - * value. Each closure should return the value of the corresponding property. - * The special "\0" key can be used to define a closure that returns all - * properties at once when full-initialization is needed; it takes the - * instance and its default properties as arguments. - * - * Properties should be indexed by their array-cast name, see - * https://php.net/manual/language.types.array#language.types.array.casting - * - * @param (\Closure(static):void - * |array - * |array{"\0": \Closure(static, array):array}) $initializer - * @param array|null $skippedProperties An array indexed by the properties to skip, aka the ones - * that the initializer doesn't set when its a closure - * @param static|null $instance - */ - public static function createLazyGhost(\Closure|array $initializer, array $skippedProperties = null, object $instance = null): static - { - $onlyProperties = null === $skippedProperties && \is_array($initializer) ? $initializer : null; - - if (self::class !== $class = $instance ? $instance::class : static::class) { - $skippedProperties["\0".self::class."\0lazyObjectState"] = true; - } elseif (\defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) { - Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES; - } - - $instance ??= (Registry::$classReflectors[$class] ??= new \ReflectionClass($class))->newInstanceWithoutConstructor(); - Registry::$defaultProperties[$class] ??= (array) $instance; - $instance->lazyObjectState = new LazyObjectState($initializer, $skippedProperties ??= []); - - foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) { - $reset($instance, $skippedProperties, $onlyProperties); - } - - return $instance; - } - - /** - * Returns whether the object is initialized. - * - * @param $partial Whether partially initialized objects should be considered as initialized - */ - public function isLazyObjectInitialized(bool $partial = false): bool - { - if (!$state = $this->lazyObjectState ?? null) { - return true; - } - - if (!\is_array($state->initializer)) { - return LazyObjectState::STATUS_INITIALIZED_FULL === $state->status; - } - - $class = $this::class; - $properties = (array) $this; - - if ($partial) { - return (bool) array_intersect_key($state->initializer, $properties); - } - - $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); - foreach ($state->initializer as $key => $initializer) { - if (!\array_key_exists($key, $properties) && isset($propertyScopes[$key])) { - return false; - } - } - - return true; - } - - /** - * Forces initialization of a lazy object and returns it. - */ - public function initializeLazyObject(): static - { - if (!$state = $this->lazyObjectState ?? null) { - return $this; - } - - if (!\is_array($state->initializer)) { - if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) { - $state->initialize($this, '', null); - } - - return $this; - } - - $values = isset($state->initializer["\0"]) ? null : []; - - $class = $this::class; - $properties = (array) $this; - $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class); - foreach ($state->initializer as $key => $initializer) { - if (\array_key_exists($key, $properties) || ![$scope, $name, $readonlyScope] = $propertyScopes[$key] ?? null) { - continue; - } - $scope = $readonlyScope ?? ('*' !== $scope ? $scope : $class); - - if (null === $values) { - if (!\is_array($values = ($state->initializer["\0"])($this, Registry::$defaultProperties[$class]))) { - throw new \TypeError(sprintf('The lazy-initializer defined for instance of "%s" must return an array, got "%s".', $class, get_debug_type($values))); - } - - if (\array_key_exists($key, $properties = (array) $this)) { - continue; - } - } - - if (\array_key_exists($key, $values)) { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['set']($this, $name, $properties[$key] = $values[$key]); - } else { - $state->initialize($this, $name, $scope); - $properties = (array) $this; - } - } - - return $this; - } - - /** - * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object - */ - public function resetLazyObject(): bool - { - if (!$state = $this->lazyObjectState ?? null) { - return false; - } - - if (LazyObjectState::STATUS_UNINITIALIZED_FULL !== $state->status) { - $state->reset($this); - } - - return true; - } - - public function &__get($name): mixed - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - - if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScope($propertyScopes, $class, $name); - $state = $this->lazyObjectState ?? null; - - if ($state && (null === $scope || isset($propertyScopes["\0$scope\0$name"])) - && LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $readonlyScope ?? $scope) - ) { - goto get_in_scope; - } - } - - if ($parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get']) { - if (2 === $parent) { - return parent::__get($name); - } - $value = parent::__get($name); - - return $value; - } - - if (null === $class) { - $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]; - trigger_error(sprintf('Undefined property: %s::$%s in %s on line %s', $this::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE); - } - - get_in_scope: - - try { - if (null === $scope) { - if (null === $readonlyScope) { - return $this->$name; - } - $value = $this->$name; - - return $value; - } - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - - return $accessor['get']($this, $name, null !== $readonlyScope); - } catch (\Error $e) { - if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) { - throw $e; - } - - try { - if (null === $scope) { - $this->$name = []; - - return $this->$name; - } - - $accessor['set']($this, $name, []); - - return $accessor['get']($this, $name, null !== $readonlyScope); - } catch (\Error) { - throw $e; - } - } - } - - public function __set($name, $value): void - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - - if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope); - $state = $this->lazyObjectState ?? null; - - if ($state && ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"]))) { - if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) { - $state->initialize($this, $name, $readonlyScope ?? $scope); - } - goto set_in_scope; - } - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) { - parent::__set($name, $value); - - return; - } - - set_in_scope: - - if (null === $scope) { - $this->$name = $value; - } else { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['set']($this, $name, $value); - } - } - - public function __isset($name): bool - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - - if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScope($propertyScopes, $class, $name); - $state = $this->lazyObjectState ?? null; - - if ($state && (null === $scope || isset($propertyScopes["\0$scope\0$name"])) - && LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $readonlyScope ?? $scope) - ) { - goto isset_in_scope; - } - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) { - return parent::__isset($name); - } - - isset_in_scope: - - if (null === $scope) { - return isset($this->$name); - } - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - - return $accessor['isset']($this, $name); - } - - public function __unset($name): void - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - - if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope); - $state = $this->lazyObjectState ?? null; - - if ($state && ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"]))) { - if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) { - $state->initialize($this, $name, $readonlyScope ?? $scope); - } - goto unset_in_scope; - } - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) { - parent::__unset($name); - - return; - } - - unset_in_scope: - - if (null === $scope) { - unset($this->$name); - } else { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['unset']($this, $name); - } - } - - public function __clone(): void - { - if ($state = $this->lazyObjectState ?? null) { - $this->lazyObjectState = clone $state; - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) { - parent::__clone(); - } - } - - public function __serialize(): array - { - $class = self::class; - - if ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) { - $properties = parent::__serialize(); - } else { - $this->initializeLazyObject(); - $properties = (array) $this; - } - unset($properties["\0$class\0lazyObjectState"]); - - if (Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) { - return $properties; - } - - $scope = get_parent_class($class); - $data = []; - - foreach (parent::__sleep() as $name) { - $value = $properties[$k = $name] ?? $properties[$k = "\0*\0$name"] ?? $properties[$k = "\0$scope\0$name"] ?? $k = null; - - if (null === $k) { - trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE); - } else { - $data[$k] = $value; - } - } - - return $data; - } - - public function __destruct() - { - $state = $this->lazyObjectState ?? null; - - if ($state && \in_array($state->status, [LazyObjectState::STATUS_UNINITIALIZED_FULL, LazyObjectState::STATUS_UNINITIALIZED_PARTIAL], true)) { - return; - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) { - parent::__destruct(); - } - } - - private function setLazyObjectAsInitialized(bool $initialized): void - { - $state = $this->lazyObjectState ?? null; - - if ($state && !\is_array($state->initializer)) { - $state->status = $initialized ? LazyObjectState::STATUS_INITIALIZED_FULL : LazyObjectState::STATUS_UNINITIALIZED_FULL; - } - } -} diff --git a/vendor/symfony/var-exporter/LazyObjectInterface.php b/vendor/symfony/var-exporter/LazyObjectInterface.php deleted file mode 100644 index 367088459..000000000 --- a/vendor/symfony/var-exporter/LazyObjectInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -interface LazyObjectInterface -{ - /** - * Returns whether the object is initialized. - * - * @param $partial Whether partially initialized objects should be considered as initialized - */ - public function isLazyObjectInitialized(bool $partial = false): bool; - - /** - * Forces initialization of a lazy object and returns it. - */ - public function initializeLazyObject(): object; - - /** - * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object - */ - public function resetLazyObject(): bool; -} diff --git a/vendor/symfony/var-exporter/LazyProxyTrait.php b/vendor/symfony/var-exporter/LazyProxyTrait.php deleted file mode 100644 index 153c38208..000000000 --- a/vendor/symfony/var-exporter/LazyProxyTrait.php +++ /dev/null @@ -1,347 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Hydrator as PublicHydrator; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry; -use Symfony\Component\VarExporter\Internal\LazyObjectState; -use Symfony\Component\VarExporter\Internal\LazyObjectTrait; - -trait LazyProxyTrait -{ - use LazyObjectTrait; - - /** - * Creates a lazy-loading virtual proxy. - * - * @param \Closure():object $initializer Returns the proxied object - * @param static|null $instance - */ - public static function createLazyProxy(\Closure $initializer, object $instance = null): static - { - if (self::class !== $class = $instance ? $instance::class : static::class) { - $skippedProperties = ["\0".self::class."\0lazyObjectState" => true]; - } elseif (\defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) { - Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES; - } - - $instance ??= (Registry::$classReflectors[$class] ??= new \ReflectionClass($class))->newInstanceWithoutConstructor(); - $instance->lazyObjectState = new LazyObjectState($initializer); - - foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) { - $reset($instance, $skippedProperties ??= []); - } - - return $instance; - } - - /** - * Returns whether the object is initialized. - * - * @param $partial Whether partially initialized objects should be considered as initialized - */ - public function isLazyObjectInitialized(bool $partial = false): bool - { - return !isset($this->lazyObjectState) || isset($this->lazyObjectState->realInstance) || Registry::$noInitializerState === $this->lazyObjectState->initializer; - } - - /** - * Forces initialization of a lazy object and returns it. - */ - public function initializeLazyObject(): parent - { - if ($state = $this->lazyObjectState ?? null) { - return $state->realInstance ??= ($state->initializer)(); - } - - return $this; - } - - /** - * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object - */ - public function resetLazyObject(): bool - { - if (!isset($this->lazyObjectState) || Registry::$noInitializerState === $this->lazyObjectState->initializer) { - return false; - } - - unset($this->lazyObjectState->realInstance); - - return true; - } - - public function &__get($name): mixed - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - $instance = $this; - - if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScope($propertyScopes, $class, $name); - - if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) { - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } - $parent = 2; - goto get_in_scope; - } - } - $parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get']; - - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } else { - if (2 === $parent) { - return parent::__get($name); - } - $value = parent::__get($name); - - return $value; - } - - if (!$parent && null === $class && !\array_key_exists($name, (array) $instance)) { - $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]; - trigger_error(sprintf('Undefined property: %s::$%s in %s on line %s', $instance::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE); - } - - get_in_scope: - - try { - if (null === $scope) { - if (null === $readonlyScope && 1 !== $parent) { - return $instance->$name; - } - $value = $instance->$name; - - return $value; - } - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - - return $accessor['get']($instance, $name, null !== $readonlyScope || 1 === $parent); - } catch (\Error $e) { - if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) { - throw $e; - } - - try { - if (null === $scope) { - $instance->$name = []; - - return $instance->$name; - } - - $accessor['set']($instance, $name, []); - - return $accessor['get']($instance, $name, null !== $readonlyScope || 1 === $parent); - } catch (\Error) { - throw $e; - } - } - } - - public function __set($name, $value): void - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - $instance = $this; - - if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope); - - if ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) { - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } - goto set_in_scope; - } - } - - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) { - parent::__set($name, $value); - - return; - } - - set_in_scope: - - if (null === $scope) { - $instance->$name = $value; - } else { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['set']($instance, $name, $value); - } - } - - public function __isset($name): bool - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - $instance = $this; - - if ([$class] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScope($propertyScopes, $class, $name); - - if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) { - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } - goto isset_in_scope; - } - } - - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) { - return parent::__isset($name); - } - - isset_in_scope: - - if (null === $scope) { - return isset($instance->$name); - } - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - - return $accessor['isset']($instance, $name); - } - - public function __unset($name): void - { - $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class); - $scope = null; - $instance = $this; - - if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) { - $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope); - - if ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) { - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } - goto unset_in_scope; - } - } - - if ($state = $this->lazyObjectState ?? null) { - $instance = $state->realInstance ??= ($state->initializer)(); - } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) { - parent::__unset($name); - - return; - } - - unset_in_scope: - - if (null === $scope) { - unset($instance->$name); - } else { - $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope); - $accessor['unset']($instance, $name); - } - } - - public function __clone(): void - { - if (!isset($this->lazyObjectState)) { - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) { - parent::__clone(); - } - - return; - } - - $this->lazyObjectState = clone $this->lazyObjectState; - - if (isset($this->lazyObjectState->realInstance)) { - $this->lazyObjectState->realInstance = clone $this->lazyObjectState->realInstance; - } - } - - public function __serialize(): array - { - $class = self::class; - $state = $this->lazyObjectState ?? null; - - if (!$state && (Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) { - $properties = parent::__serialize(); - } else { - $properties = (array) $this; - - if ($state) { - unset($properties["\0$class\0lazyObjectState"]); - $properties["\0$class\0lazyObjectReal"] = $state->realInstance ??= ($state->initializer)(); - } - } - - if ($state || Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) { - return $properties; - } - - $scope = get_parent_class($class); - $data = []; - - foreach (parent::__sleep() as $name) { - $value = $properties[$k = $name] ?? $properties[$k = "\0*\0$name"] ?? $properties[$k = "\0$scope\0$name"] ?? $k = null; - - if (null === $k) { - trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE); - } else { - $data[$k] = $value; - } - } - - return $data; - } - - public function __unserialize(array $data): void - { - $class = self::class; - - if ($instance = $data["\0$class\0lazyObjectReal"] ?? null) { - unset($data["\0$class\0lazyObjectReal"]); - - foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) { - $reset($this, $data); - } - - if ($data) { - PublicHydrator::hydrate($this, $data); - } - $this->lazyObjectState = new LazyObjectState(Registry::$noInitializerState ??= static fn () => throw new \LogicException('Lazy proxy has no initializer.')); - $this->lazyObjectState->realInstance = $instance; - } elseif ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['unserialize']) { - parent::__unserialize($data); - } else { - PublicHydrator::hydrate($this, $data); - - if (Registry::$parentMethods[$class]['wakeup']) { - parent::__wakeup(); - } - } - } - - public function __destruct() - { - if (isset($this->lazyObjectState)) { - return; - } - - if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) { - parent::__destruct(); - } - } -} diff --git a/vendor/symfony/var-exporter/ProxyHelper.php b/vendor/symfony/var-exporter/ProxyHelper.php deleted file mode 100644 index 2e150cb5c..000000000 --- a/vendor/symfony/var-exporter/ProxyHelper.php +++ /dev/null @@ -1,365 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Exception\LogicException; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\LazyObjectRegistry; - -/** - * @author Nicolas Grekas - */ -final class ProxyHelper -{ - /** - * Helps generate lazy-loading ghost objects. - * - * @throws LogicException When the class is incompatible with ghost objects - */ - public static function generateLazyGhost(\ReflectionClass $class): string - { - if (\PHP_VERSION_ID >= 80200 && \PHP_VERSION_ID < 80300 && $class->isReadOnly()) { - throw new LogicException(sprintf('Cannot generate lazy ghost: class "%s" is readonly.', $class->name)); - } - if ($class->isFinal()) { - throw new LogicException(sprintf('Cannot generate lazy ghost: class "%s" is final.', $class->name)); - } - if ($class->isInterface() || $class->isAbstract()) { - throw new LogicException(sprintf('Cannot generate lazy ghost: "%s" is not a concrete class.', $class->name)); - } - if (\stdClass::class !== $class->name && $class->isInternal()) { - throw new LogicException(sprintf('Cannot generate lazy ghost: class "%s" is internal.', $class->name)); - } - if ($class->hasMethod('__get') && 'mixed' !== (self::exportType($class->getMethod('__get')) ?? 'mixed')) { - throw new LogicException(sprintf('Cannot generate lazy ghost: return type of method "%s::__get()" should be "mixed".', $class->name)); - } - - static $traitMethods; - $traitMethods ??= (new \ReflectionClass(LazyGhostTrait::class))->getMethods(); - - foreach ($traitMethods as $method) { - if ($class->hasMethod($method->name) && $class->getMethod($method->name)->isFinal()) { - throw new LogicException(sprintf('Cannot generate lazy ghost: method "%s::%s()" is final.', $class->name, $method->name)); - } - } - - $parent = $class; - while ($parent = $parent->getParentClass()) { - if (\stdClass::class !== $parent->name && $parent->isInternal()) { - throw new LogicException(sprintf('Cannot generate lazy ghost: class "%s" extends "%s" which is internal.', $class->name, $parent->name)); - } - } - $propertyScopes = self::exportPropertyScopes($class->name); - - return <<name} implements \Symfony\Component\VarExporter\LazyObjectInterface - { - use \Symfony\Component\VarExporter\LazyGhostTrait; - - private const LAZY_OBJECT_PROPERTY_SCOPES = {$propertyScopes}; - } - - // Help opcache.preload discover always-needed symbols - class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class); - class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); - - EOPHP; - } - - /** - * Helps generate lazy-loading virtual proxies. - * - * @param \ReflectionClass[] $interfaces - * - * @throws LogicException When the class is incompatible with virtual proxies - */ - public static function generateLazyProxy(?\ReflectionClass $class, array $interfaces = []): string - { - if (!class_exists($class?->name ?? \stdClass::class, false)) { - throw new LogicException(sprintf('Cannot generate lazy proxy: "%s" is not a class.', $class->name)); - } - if ($class?->isFinal()) { - throw new LogicException(sprintf('Cannot generate lazy proxy: class "%s" is final.', $class->name)); - } - if (\PHP_VERSION_ID >= 80200 && \PHP_VERSION_ID < 80300 && $class?->isReadOnly()) { - throw new LogicException(sprintf('Cannot generate lazy proxy: class "%s" is readonly.', $class->name)); - } - - $methodReflectors = [$class?->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) ?? []]; - foreach ($interfaces as $interface) { - if (!$interface->isInterface()) { - throw new LogicException(sprintf('Cannot generate lazy proxy: "%s" is not an interface.', $interface->name)); - } - $methodReflectors[] = $interface->getMethods(); - } - $methodReflectors = array_merge(...$methodReflectors); - - $extendsInternalClass = false; - if ($parent = $class) { - do { - $extendsInternalClass = \stdClass::class !== $parent->name && $parent->isInternal(); - } while (!$extendsInternalClass && $parent = $parent->getParentClass()); - } - $methodsHaveToBeProxied = $extendsInternalClass; - $methods = []; - - foreach ($methodReflectors as $method) { - if ('__get' !== strtolower($method->name) || 'mixed' === ($type = self::exportType($method) ?? 'mixed')) { - continue; - } - $methodsHaveToBeProxied = true; - $trait = new \ReflectionMethod(LazyProxyTrait::class, '__get'); - $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine()); - $body[0] = str_replace('): mixed', '): '.$type, $body[0]); - $methods['__get'] = strtr(implode('', $body).' }', [ - 'Hydrator' => '\\'.Hydrator::class, - 'Registry' => '\\'.LazyObjectRegistry::class, - ]); - break; - } - - foreach ($methodReflectors as $method) { - if (($method->isStatic() && !$method->isAbstract()) || isset($methods[$lcName = strtolower($method->name)])) { - continue; - } - if ($method->isFinal()) { - if ($extendsInternalClass || $methodsHaveToBeProxied || method_exists(LazyProxyTrait::class, $method->name)) { - throw new LogicException(sprintf('Cannot generate lazy proxy: method "%s::%s()" is final.', $class->name, $method->name)); - } - continue; - } - if (method_exists(LazyProxyTrait::class, $method->name) || ($method->isProtected() && !$method->isAbstract())) { - continue; - } - - $signature = self::exportSignature($method, true, $args); - $parentCall = $method->isAbstract() ? "throw new \BadMethodCallException('Cannot forward abstract method \"{$method->class}::{$method->name}()\".')" : "parent::{$method->name}({$args})"; - - if ($method->isStatic()) { - $body = " $parentCall;"; - } elseif (str_ends_with($signature, '): never') || str_ends_with($signature, '): void')) { - $body = <<lazyObjectState)) { - (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); - } else { - {$parentCall}; - } - EOPHP; - } else { - if (!$methodsHaveToBeProxied && !$method->isAbstract()) { - // Skip proxying methods that might return $this - foreach (preg_split('/[()|&]++/', self::exportType($method) ?? 'static') as $type) { - if (\in_array($type = ltrim($type, '?'), ['static', 'object'], true)) { - continue 2; - } - foreach ([$class, ...$interfaces] as $r) { - if ($r && is_a($r->name, $type, true)) { - continue 3; - } - } - } - } - - $body = <<lazyObjectState)) { - return (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args}); - } - - return {$parentCall}; - EOPHP; - } - $methods[$lcName] = " {$signature}\n {\n{$body}\n }"; - } - - $types = $interfaces = array_unique(array_column($interfaces, 'name')); - $interfaces[] = LazyObjectInterface::class; - $interfaces = implode(', \\', $interfaces); - $parent = $class ? ' extends \\'.$class->name : ''; - array_unshift($types, $class ? 'parent' : ''); - $type = ltrim(implode('&\\', $types), '&'); - - if (!$class) { - $trait = new \ReflectionMethod(LazyProxyTrait::class, 'initializeLazyObject'); - $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine()); - $body[0] = str_replace('): parent', '): '.$type, $body[0]); - $methods = ['initializeLazyObject' => implode('', $body).' }'] + $methods; - } - $body = $methods ? "\n".implode("\n\n", $methods)."\n" : ''; - $propertyScopes = $class ? self::exportPropertyScopes($class->name) : '[]'; - - return <<getParameters() as $param) { - $parameters[] = ($param->getAttributes(\SensitiveParameter::class) ? '#[\SensitiveParameter] ' : '') - .($withParameterTypes && $param->hasType() ? self::exportType($param).' ' : '') - .($param->isPassedByReference() ? '&' : '') - .($param->isVariadic() ? '...' : '').'$'.$param->name - .($param->isOptional() && !$param->isVariadic() ? ' = '.self::exportDefault($param) : ''); - $hasByRef = $hasByRef || $param->isPassedByReference(); - $args .= ($param->isVariadic() ? '...$' : '$').$param->name.', '; - } - - if (!$param || !$hasByRef) { - $args = '...\func_get_args()'; - } elseif ($param->isVariadic()) { - $args = substr($args, 0, -2); - } else { - $args .= sprintf('...\array_slice(\func_get_args(), %d)', \count($parameters)); - } - - $signature = 'function '.($function->returnsReference() ? '&' : '') - .($function->isClosure() ? '' : $function->name).'('.implode(', ', $parameters).')'; - - if ($function instanceof \ReflectionMethod) { - $signature = ($function->isPublic() ? 'public ' : ($function->isProtected() ? 'protected ' : 'private ')) - .($function->isStatic() ? 'static ' : '').$signature; - } - if ($function->hasReturnType()) { - $signature .= ': '.self::exportType($function); - } - - static $getPrototype; - $getPrototype ??= (new \ReflectionMethod(\ReflectionMethod::class, 'getPrototype'))->invoke(...); - - while ($function) { - if ($function->hasTentativeReturnType()) { - return '#[\ReturnTypeWillChange] '.$signature; - } - - try { - $function = $function instanceof \ReflectionMethod && $function->isAbstract() ? false : $getPrototype($function); - } catch (\ReflectionException) { - break; - } - } - - return $signature; - } - - public static function exportType(\ReflectionFunctionAbstract|\ReflectionProperty|\ReflectionParameter $owner, bool $noBuiltin = false, \ReflectionType $type = null): ?string - { - if (!$type ??= $owner instanceof \ReflectionFunctionAbstract ? $owner->getReturnType() : $owner->getType()) { - return null; - } - $class = null; - $types = []; - if ($type instanceof \ReflectionUnionType) { - $reflectionTypes = $type->getTypes(); - $glue = '|'; - } elseif ($type instanceof \ReflectionIntersectionType) { - $reflectionTypes = $type->getTypes(); - $glue = '&'; - } else { - $reflectionTypes = [$type]; - $glue = null; - } - - foreach ($reflectionTypes as $type) { - if ($type instanceof \ReflectionIntersectionType) { - if ('' !== $name = '('.self::exportType($owner, $noBuiltin, $type).')') { - $types[] = $name; - } - continue; - } - $name = $type->getName(); - - if ($noBuiltin && $type->isBuiltin()) { - continue; - } - if (\in_array($name, ['parent', 'self'], true) && $class ??= $owner->getDeclaringClass()) { - $name = 'parent' === $name ? ($class->getParentClass() ?: null)?->name ?? 'parent' : $class->name; - } - - $types[] = ($noBuiltin || $type->isBuiltin() || 'static' === $name ? '' : '\\').$name; - } - - if (!$types) { - return ''; - } - if (null === $glue) { - return (!$noBuiltin && $type->allowsNull() && 'mixed' !== $name ? '?' : '').$types[0]; - } - sort($types); - - return implode($glue, $types); - } - - private static function exportPropertyScopes(string $parent): string - { - $propertyScopes = Hydrator::$propertyScopes[$parent] ??= Hydrator::getPropertyScopes($parent); - uksort($propertyScopes, 'strnatcmp'); - $propertyScopes = VarExporter::export($propertyScopes); - $propertyScopes = str_replace(VarExporter::export($parent), 'parent::class', $propertyScopes); - $propertyScopes = preg_replace("/(?|(,)\n( ) |\n |,\n (\]))/", '$1$2', $propertyScopes); - $propertyScopes = str_replace("\n", "\n ", $propertyScopes); - - return $propertyScopes; - } - - private static function exportDefault(\ReflectionParameter $param): string - { - $default = rtrim(substr(explode('$'.$param->name.' = ', (string) $param, 2)[1] ?? '', 0, -2)); - - if (\in_array($default, ['', 'NULL'], true)) { - return 'null'; - } - if (str_ends_with($default, "...'") && preg_match("/^'(?:[^'\\\\]*+(?:\\\\.)*+)*+'$/", $default)) { - return VarExporter::export($param->getDefaultValue()); - } - - $regexp = "/(\"(?:[^\"\\\\]*+(?:\\\\.)*+)*+\"|'(?:[^'\\\\]*+(?:\\\\.)*+)*+')/"; - $parts = preg_split($regexp, $default, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); - - $regexp = '/([\[\( ]|^)([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z0-9_\x7f-\xff]++)*+)(?!: )/'; - $callback = (false !== strpbrk($default, "\\:('") && $class = $param->getDeclaringClass()) - ? fn ($m) => $m[1].match ($m[2]) { - 'new', 'false', 'true', 'null' => $m[2], - 'NULL' => 'null', - 'self' => '\\'.$class->name, - 'namespace\\parent', - 'parent' => ($parent = $class->getParentClass()) ? '\\'.$parent->name : 'parent', - default => '\\'.$m[2], - } - : fn ($m) => $m[1].match ($m[2]) { - 'new', 'false', 'true', 'null', 'self', 'parent' => $m[2], - 'NULL' => 'null', - default => '\\'.$m[2], - }; - - return implode('', array_map(fn ($part) => match ($part[0]) { - '"' => $part, // for internal classes only - "'" => false !== strpbrk($part, "\\\0\r\n") ? '"'.substr(str_replace(['$', "\0", "\r", "\n"], ['\$', '\0', '\r', '\n'], $part), 1, -1).'"' : $part, - default => preg_replace_callback($regexp, $callback, $part), - }, $parts)); - } -} diff --git a/vendor/symfony/var-exporter/README.md b/vendor/symfony/var-exporter/README.md index 7c7a58e29..a34e4c23d 100644 --- a/vendor/symfony/var-exporter/README.md +++ b/vendor/symfony/var-exporter/README.md @@ -1,22 +1,15 @@ VarExporter Component ===================== -The VarExporter component provides various tools to deal with the internal state -of objects: +The VarExporter component allows exporting any serializable PHP data structure to +plain PHP code. While doing so, it preserves all the semantics associated with +the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, +`__serialize`, `__unserialize`). -- `VarExporter::export()` allows exporting any serializable PHP data structure to - plain PHP code. While doing so, it preserves all the semantics associated with - the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, - `__serialize`, `__unserialize`.) -- `Instantiator::instantiate()` creates an object and sets its properties without - calling its constructor nor any other methods. -- `Hydrator::hydrate()` can set the properties of an existing object. -- `Lazy*Trait` can make a class behave as a lazy-loading ghost or virtual proxy. +It also provides an instantiator that allows creating and populating objects +without calling their constructor nor any other methods. -VarExporter::export() ---------------------- - -The reason to use `VarExporter::export()` *vs* `serialize()` or +The reason to use this component *vs* `serialize()` or [igbinary](https://github.com/igbinary/igbinary) is performance: thanks to OPcache, the resulting code is significantly faster and more memory efficient than using `unserialize()` or `igbinary_unserialize()`. @@ -27,118 +20,14 @@ It also provides a few improvements over `var_export()`/`serialize()`: * the output is PSR-2 compatible; * the output can be re-indented without messing up with `\r` or `\n` in the data - * missing classes throw a `ClassNotFoundException` instead of being unserialized - to `PHP_Incomplete_Class` objects; + * missing classes throw a `ClassNotFoundException` instead of being unserialized to + `PHP_Incomplete_Class` objects; * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator` instances are preserved; * `Reflection*`, `IteratorIterator` and `RecursiveIteratorIterator` classes throw an exception when being serialized (their unserialized version is broken anyway, see https://bugs.php.net/76737). -Instantiator and Hydrator -------------------------- - -`Instantiator::instantiate($class)` creates an object of the given class without -calling its constructor nor any other methods. - -`Hydrator::hydrate()` sets the properties of an existing object, including -private and protected ones. For example: - -```php -// Sets the public or protected $object->propertyName property -Hydrator::hydrate($object, ['propertyName' => $propertyValue]); - -// Sets a private property defined on its parent Bar class: -Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]); - -// Alternative way to set the private $object->privateBarProperty property -Hydrator::hydrate($object, [], [ - Bar::class => ['privateBarProperty' => $propertyValue], -]); -``` - -`Lazy*Trait` ------------- - -The component provides two lazy-loading patterns: ghost objects and virtual -proxies (see https://martinfowler.com/eaaCatalog/lazyLoad.html for reference.) - -Ghost objects work only with concrete and non-internal classes. In the generic -case, they are not compatible with using factories in their initializer. - -Virtual proxies work with concrete, abstract or internal classes. They provide an -API that looks like the actual objects and forward calls to them. They can cause -identity problems because proxies might not be seen as equivalents to the actual -objects they proxy. - -Because of this identity problem, ghost objects should be preferred when -possible. Exceptions thrown by the `ProxyHelper` class can help decide when it -can be used or not. - -Ghost objects and virtual proxies both provide implementations for the -`LazyObjectInterface` which allows resetting them to their initial state or to -forcibly initialize them when needed. Note that resetting a ghost object skips -its read-only properties. You should use a virtual proxy to reset read-only -properties. - -### `LazyGhostTrait` - -By using `LazyGhostTrait` either directly in your classes or by using -`ProxyHelper::generateLazyGhost()`, you can make their instances lazy-loadable. -This works by creating these instances empty and by computing their state only -when accessing a property. - -```php -class FooLazyGhost extends Foo -{ - use LazyGhostTrait; -} - -$foo = FooLazyGhost::createLazyGhost(initializer: function (Foo $instance): void { - // [...] Use whatever heavy logic you need here - // to compute the $dependencies of the $instance - $instance->__construct(...$dependencies); - // [...] Call setters, etc. if needed -}); - -// $foo is now a lazy-loading ghost object. The initializer will -// be called only when and if a *property* is accessed. -``` - -You can also partially initialize the objects on a property-by-property basis by -adding two arguments to the initializer: - -```php -$initializer = function (Foo $instance, string $propertyName, ?string $propertyScope): mixed { - if (Foo::class === $propertyScope && 'bar' === $propertyName) { - return 123; - } - // [...] Add more logic for the other properties -}; -``` - -### `LazyProxyTrait` - -Alternatively, `LazyProxyTrait` can be used to create virtual proxies: - -```php -$proxyCode = ProxyHelper::generateLazyProxy(new ReflectionClass(Foo::class)); -// $proxyCode contains the reference to LazyProxyTrait -// and should be dumped into a file in production envs -eval('class FooLazyProxy'.$proxyCode); - -$foo = FooLazyProxy::createLazyProxy(initializer: function (): Foo { - // [...] Use whatever heavy logic you need here - // to compute the $dependencies of the $instance - $instance = new Foo(...$dependencies); - // [...] Call setters, etc. if needed - - return $instance; -}); -// $foo is now a lazy-loading virtual proxy object. The initializer will -// be called only when and if a *method* is called. -``` - Resources --------- diff --git a/vendor/symfony/var-exporter/VarExporter.php b/vendor/symfony/var-exporter/VarExporter.php index c12eb4f95..3e2a4cc03 100644 --- a/vendor/symfony/var-exporter/VarExporter.php +++ b/vendor/symfony/var-exporter/VarExporter.php @@ -32,8 +32,8 @@ final class VarExporter /** * Exports a serializable PHP value to PHP code. * - * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise - * @param array &$foundClasses Classes found in the value are added to this list as both keys and values + * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise + * @param bool &$classes Classes found in the value are added to this list as both keys and values * * @throws ExceptionInterface When the provided value cannot be serialized */ diff --git a/vendor/symfony/var-exporter/composer.json b/vendor/symfony/var-exporter/composer.json index 83140ee7d..3bf21a64e 100644 --- a/vendor/symfony/var-exporter/composer.json +++ b/vendor/symfony/var-exporter/composer.json @@ -2,7 +2,7 @@ "name": "symfony/var-exporter", "type": "library", "description": "Allows exporting any serializable PHP data structure to plain PHP code", - "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone", "lazy-loading", "proxy"], + "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=8.1" + "php": ">=8.0.2" }, "require-dev": { "symfony/var-dumper": "^5.4|^6.0" diff --git a/vendor/w7corp/easywechat/composer.json b/vendor/w7corp/easywechat/composer.json index 7fe28afb8..a52d0947a 100644 --- a/vendor/w7corp/easywechat/composer.json +++ b/vendor/w7corp/easywechat/composer.json @@ -23,10 +23,10 @@ "ext-sodium": "*", "ext-libxml": "*", "ext-curl": "*", - "monolog/monolog": "^2.2|^3.0", + "monolog/monolog": "^2.2", "nyholm/psr7": "^1.5", "nyholm/psr7-server": "^1.0", - "overtrue/socialite": "^3.5.4|^4.0.1", + "overtrue/socialite": "^3.5|^4.0.1", "psr/simple-cache": "^1.0|^2.0|^3.0", "psr/http-client": "^1.0", "symfony/cache": "^5.4|^6.0", diff --git a/vendor/w7corp/easywechat/docs/.npmrc b/vendor/w7corp/easywechat/docs/.npmrc deleted file mode 100644 index 3e775efb0..000000000 --- a/vendor/w7corp/easywechat/docs/.npmrc +++ /dev/null @@ -1 +0,0 @@ -auto-install-peers=true diff --git a/vendor/w7corp/easywechat/docs/package.json b/vendor/w7corp/easywechat/docs/package.json index c14694752..078544f0a 100644 --- a/vendor/w7corp/easywechat/docs/package.json +++ b/vendor/w7corp/easywechat/docs/package.json @@ -6,19 +6,20 @@ "preinstall": "npx only-allow pnpm" }, "dependencies": { - "autoprefixer": "^10.4.12", + "@overtrue/easywechat-theme": "^1.0.5", + "autoprefixer": "^10.4.7", "clipboard": "^2.0.11", "dynamics.js": "^1.1.5", - "gsap": "^3.11.3", - "tailwindcss": "^3.1.8" + "gsap": "^3.10.4", + "postcss": "^8.4.14", + "postcss-import": "^14.1.0", + "tailwindcss": "^3.1.4", + "vitepress": "1.0.0-alpha.4", + "vue": "^3.2.37" }, "devDependencies": { "@types/markdown-it": "^12.2.3", - "@types/node": "^16.11.65", - "vitepress": "1.0.0-alpha.21", - "postcss": "^8.4.18", - "postcss-import": "^14.1.0", - "terser": "^5.15.1" + "@types/node": "^16.11.41" }, "pnpm": { "peerDependencyRules": { diff --git a/vendor/w7corp/easywechat/docs/pnpm-lock.yaml b/vendor/w7corp/easywechat/docs/pnpm-lock.yaml index bdf230649..497b7508e 100644 --- a/vendor/w7corp/easywechat/docs/pnpm-lock.yaml +++ b/vendor/w7corp/easywechat/docs/pnpm-lock.yaml @@ -1,193 +1,175 @@ lockfileVersion: 5.4 specifiers: + '@overtrue/easywechat-theme': ^1.0.5 '@types/markdown-it': ^12.2.3 - '@types/node': ^16.11.65 - autoprefixer: ^10.4.12 + '@types/node': ^16.11.41 + autoprefixer: ^10.4.7 clipboard: ^2.0.11 dynamics.js: ^1.1.5 - gsap: ^3.11.3 - postcss: ^8.4.18 + gsap: ^3.10.4 + postcss: ^8.4.14 postcss-import: ^14.1.0 - tailwindcss: ^3.1.8 - terser: ^5.15.1 - vitepress: 1.0.0-alpha.21 + tailwindcss: ^3.1.4 + vitepress: 1.0.0-alpha.4 + vue: ^3.2.37 dependencies: - autoprefixer: 10.4.12_postcss@8.4.18 + '@overtrue/easywechat-theme': 1.0.5_vue@3.2.37 + autoprefixer: 10.4.7_postcss@8.4.14 clipboard: 2.0.11 dynamics.js: 1.1.5 - gsap: 3.11.3 - tailwindcss: 3.1.8 + gsap: 3.10.4 + postcss: 8.4.14 + postcss-import: 14.1.0_postcss@8.4.14 + tailwindcss: 3.1.4 + vitepress: 1.0.0-alpha.4 + vue: 3.2.37 devDependencies: '@types/markdown-it': 12.2.3 - '@types/node': 16.11.65 - postcss: 8.4.18 - postcss-import: 14.1.0_postcss@8.4.18 - terser: 5.15.1 - vitepress: 1.0.0-alpha.21_terser@5.15.1 + '@types/node': 16.11.41 packages: - /@algolia/autocomplete-core/1.7.1: - resolution: {integrity: sha512-eiZw+fxMzNQn01S8dA/hcCpoWCOCwcIIEUtHHdzN5TGB3IpzLbuhqFeTfh2OUhhgkE8Uo17+wH+QJ/wYyQmmzg==} + /@algolia/autocomplete-core/1.6.3: + resolution: {integrity: sha512-dqQqRt01fX3YuVFrkceHsoCnzX0bLhrrg8itJI1NM68KjrPYQPYsE+kY8EZTCM4y8VDnhqJErR73xe/ZsV+qAA==} dependencies: - '@algolia/autocomplete-shared': 1.7.1 - dev: true + '@algolia/autocomplete-shared': 1.6.3 + dev: false - /@algolia/autocomplete-preset-algolia/1.7.1_algoliasearch@4.14.2: - resolution: {integrity: sha512-pJwmIxeJCymU1M6cGujnaIYcY3QPOVYZOXhFkWVM7IxKzy272BwCvMFMyc5NpG/QmiObBxjo7myd060OeTNJXg==} - peerDependencies: - '@algolia/client-search': ^4.9.1 - algoliasearch: ^4.9.1 - peerDependenciesMeta: - '@algolia/client-search': - optional: true + /@algolia/autocomplete-shared/1.6.3: + resolution: {integrity: sha512-UV46bnkTztyADFaETfzFC5ryIdGVb2zpAoYgu0tfcuYWjhg1KbLXveFffZIrGVoboqmAk1b+jMrl6iCja1i3lg==} + dev: false + + /@algolia/cache-browser-local-storage/4.13.1: + resolution: {integrity: sha512-UAUVG2PEfwd/FfudsZtYnidJ9eSCpS+LW9cQiesePQLz41NAcddKxBak6eP2GErqyFagSlnVXe/w2E9h2m2ttg==} dependencies: - '@algolia/autocomplete-shared': 1.7.1 - algoliasearch: 4.14.2 - dev: true + '@algolia/cache-common': 4.13.1 + dev: false - /@algolia/autocomplete-shared/1.7.1: - resolution: {integrity: sha512-eTmGVqY3GeyBTT8IWiB2K5EuURAqhnumfktAEoHxfDY2o7vg2rSnO16ZtIG0fMgt3py28Vwgq42/bVEuaQV7pg==} - dev: true + /@algolia/cache-common/4.13.1: + resolution: {integrity: sha512-7Vaf6IM4L0Jkl3sYXbwK+2beQOgVJ0mKFbz/4qSxKd1iy2Sp77uTAazcX+Dlexekg1fqGUOSO7HS4Sx47ZJmjA==} + dev: false - /@algolia/cache-browser-local-storage/4.14.2: - resolution: {integrity: sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA==} + /@algolia/cache-in-memory/4.13.1: + resolution: {integrity: sha512-pZzybCDGApfA/nutsFK1P0Sbsq6fYJU3DwIvyKg4pURerlJM4qZbB9bfLRef0FkzfQu7W11E4cVLCIOWmyZeuQ==} dependencies: - '@algolia/cache-common': 4.14.2 - dev: true + '@algolia/cache-common': 4.13.1 + dev: false - /@algolia/cache-common/4.14.2: - resolution: {integrity: sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg==} - dev: true - - /@algolia/cache-in-memory/4.14.2: - resolution: {integrity: sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ==} + /@algolia/client-account/4.13.1: + resolution: {integrity: sha512-TFLiZ1KqMiir3FNHU+h3b0MArmyaHG+eT8Iojio6TdpeFcAQ1Aiy+2gb3SZk3+pgRJa/BxGmDkRUwE5E/lv3QQ==} dependencies: - '@algolia/cache-common': 4.14.2 - dev: true + '@algolia/client-common': 4.13.1 + '@algolia/client-search': 4.13.1 + '@algolia/transporter': 4.13.1 + dev: false - /@algolia/client-account/4.14.2: - resolution: {integrity: sha512-WHtriQqGyibbb/Rx71YY43T0cXqyelEU0lB2QMBRXvD2X0iyeGl4qMxocgEIcbHyK7uqE7hKgjT8aBrHqhgc1w==} + /@algolia/client-analytics/4.13.1: + resolution: {integrity: sha512-iOS1JBqh7xaL5x00M5zyluZ9+9Uy9GqtYHv/2SMuzNW1qP7/0doz1lbcsP3S7KBbZANJTFHUOfuqyRLPk91iFA==} dependencies: - '@algolia/client-common': 4.14.2 - '@algolia/client-search': 4.14.2 - '@algolia/transporter': 4.14.2 - dev: true + '@algolia/client-common': 4.13.1 + '@algolia/client-search': 4.13.1 + '@algolia/requester-common': 4.13.1 + '@algolia/transporter': 4.13.1 + dev: false - /@algolia/client-analytics/4.14.2: - resolution: {integrity: sha512-yBvBv2mw+HX5a+aeR0dkvUbFZsiC4FKSnfqk9rrfX+QrlNOKEhCG0tJzjiOggRW4EcNqRmaTULIYvIzQVL2KYQ==} + /@algolia/client-common/4.13.1: + resolution: {integrity: sha512-LcDoUE0Zz3YwfXJL6lJ2OMY2soClbjrrAKB6auYVMNJcoKZZ2cbhQoFR24AYoxnGUYBER/8B+9sTBj5bj/Gqbg==} dependencies: - '@algolia/client-common': 4.14.2 - '@algolia/client-search': 4.14.2 - '@algolia/requester-common': 4.14.2 - '@algolia/transporter': 4.14.2 - dev: true + '@algolia/requester-common': 4.13.1 + '@algolia/transporter': 4.13.1 + dev: false - /@algolia/client-common/4.14.2: - resolution: {integrity: sha512-43o4fslNLcktgtDMVaT5XwlzsDPzlqvqesRi4MjQz2x4/Sxm7zYg5LRYFol1BIhG6EwxKvSUq8HcC/KxJu3J0Q==} + /@algolia/client-personalization/4.13.1: + resolution: {integrity: sha512-1CqrOW1ypVrB4Lssh02hP//YxluoIYXAQCpg03L+/RiXJlCs+uIqlzC0ctpQPmxSlTK6h07kr50JQoYH/TIM9w==} dependencies: - '@algolia/requester-common': 4.14.2 - '@algolia/transporter': 4.14.2 - dev: true + '@algolia/client-common': 4.13.1 + '@algolia/requester-common': 4.13.1 + '@algolia/transporter': 4.13.1 + dev: false - /@algolia/client-personalization/4.14.2: - resolution: {integrity: sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw==} + /@algolia/client-search/4.13.1: + resolution: {integrity: sha512-YQKYA83MNRz3FgTNM+4eRYbSmHi0WWpo019s5SeYcL3HUan/i5R09VO9dk3evELDFJYciiydSjbsmhBzbpPP2A==} dependencies: - '@algolia/client-common': 4.14.2 - '@algolia/requester-common': 4.14.2 - '@algolia/transporter': 4.14.2 - dev: true + '@algolia/client-common': 4.13.1 + '@algolia/requester-common': 4.13.1 + '@algolia/transporter': 4.13.1 + dev: false - /@algolia/client-search/4.14.2: - resolution: {integrity: sha512-L5zScdOmcZ6NGiVbLKTvP02UbxZ0njd5Vq9nJAmPFtjffUSOGEp11BmD2oMJ5QvARgx2XbX4KzTTNS5ECYIMWw==} + /@algolia/logger-common/4.13.1: + resolution: {integrity: sha512-L6slbL/OyZaAXNtS/1A8SAbOJeEXD5JcZeDCPYDqSTYScfHu+2ePRTDMgUTY4gQ7HsYZ39N1LujOd8WBTmM2Aw==} + dev: false + + /@algolia/logger-console/4.13.1: + resolution: {integrity: sha512-7jQOTftfeeLlnb3YqF8bNgA2GZht7rdKkJ31OCeSH2/61haO0tWPoNRjZq9XLlgMQZH276pPo0NdiArcYPHjCA==} dependencies: - '@algolia/client-common': 4.14.2 - '@algolia/requester-common': 4.14.2 - '@algolia/transporter': 4.14.2 - dev: true + '@algolia/logger-common': 4.13.1 + dev: false - /@algolia/logger-common/4.14.2: - resolution: {integrity: sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA==} - dev: true - - /@algolia/logger-console/4.14.2: - resolution: {integrity: sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g==} + /@algolia/requester-browser-xhr/4.13.1: + resolution: {integrity: sha512-oa0CKr1iH6Nc7CmU6RE7TnXMjHnlyp7S80pP/LvZVABeJHX3p/BcSCKovNYWWltgTxUg0U1o+2uuy8BpMKljwA==} dependencies: - '@algolia/logger-common': 4.14.2 - dev: true + '@algolia/requester-common': 4.13.1 + dev: false - /@algolia/requester-browser-xhr/4.14.2: - resolution: {integrity: sha512-CEh//xYz/WfxHFh7pcMjQNWgpl4wFB85lUMRyVwaDPibNzQRVcV33YS+63fShFWc2+42YEipFGH2iPzlpszmDw==} + /@algolia/requester-common/4.13.1: + resolution: {integrity: sha512-eGVf0ID84apfFEuXsaoSgIxbU3oFsIbz4XiotU3VS8qGCJAaLVUC5BUJEkiFENZIhon7hIB4d0RI13HY4RSA+w==} + dev: false + + /@algolia/requester-node-http/4.13.1: + resolution: {integrity: sha512-7C0skwtLdCz5heKTVe/vjvrqgL/eJxmiEjHqXdtypcE5GCQCYI15cb+wC4ytYioZDMiuDGeVYmCYImPoEgUGPw==} dependencies: - '@algolia/requester-common': 4.14.2 - dev: true + '@algolia/requester-common': 4.13.1 + dev: false - /@algolia/requester-common/4.14.2: - resolution: {integrity: sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg==} - dev: true - - /@algolia/requester-node-http/4.14.2: - resolution: {integrity: sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg==} + /@algolia/transporter/4.13.1: + resolution: {integrity: sha512-pICnNQN7TtrcYJqqPEXByV8rJ8ZRU2hCiIKLTLRyNpghtQG3VAFk6fVtdzlNfdUGZcehSKGarPIZEHlQXnKjgw==} dependencies: - '@algolia/requester-common': 4.14.2 - dev: true + '@algolia/cache-common': 4.13.1 + '@algolia/logger-common': 4.13.1 + '@algolia/requester-common': 4.13.1 + dev: false - /@algolia/transporter/4.14.2: - resolution: {integrity: sha512-t89dfQb2T9MFQHidjHcfhh6iGMNwvuKUvojAj+JsrHAGbuSy7yE4BylhLX6R0Q1xYRoC4Vvv+O5qIw/LdnQfsQ==} - dependencies: - '@algolia/cache-common': 4.14.2 - '@algolia/logger-common': 4.14.2 - '@algolia/requester-common': 4.14.2 - dev: true - - /@babel/helper-string-parser/7.19.4: - resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} + /@babel/helper-validator-identifier/7.16.7: + resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} engines: {node: '>=6.9.0'} - dev: true + dev: false - /@babel/helper-validator-identifier/7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/parser/7.19.4: - resolution: {integrity: sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==} + /@babel/parser/7.18.5: + resolution: {integrity: sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.19.4 - dev: true + '@babel/types': 7.18.4 + dev: false - /@babel/types/7.19.4: - resolution: {integrity: sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==} + /@babel/types/7.18.4: + resolution: {integrity: sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 + '@babel/helper-validator-identifier': 7.16.7 to-fast-properties: 2.0.0 - dev: true + dev: false - /@docsearch/css/3.2.1: - resolution: {integrity: sha512-gaP6TxxwQC+K8D6TRx5WULUWKrcbzECOPA2KCVMuI+6C7dNiGUk5yXXzVhc5sld79XKYLnO9DRTI4mjXDYkh+g==} - dev: true + /@docsearch/css/3.1.0: + resolution: {integrity: sha512-bh5IskwkkodbvC0FzSg1AxMykfDl95hebEKwxNoq4e5QaGzOXSBgW8+jnMFZ7JU4sTBiB04vZWoUSzNrPboLZA==} + dev: false - /@docsearch/js/3.2.1: - resolution: {integrity: sha512-H1PekEtSeS0msetR2YGGey2w7jQ2wAKfGODJvQTygSwMgUZ+2DHpzUgeDyEBIXRIfaBcoQneqrzsljM62pm6Xg==} + /@docsearch/js/3.1.0: + resolution: {integrity: sha512-5XSK+xbP0hcTIp54MECqxkWLs6kf7Ug4nWdxWNtx8cUpLiFNFnKXDxCb35wnyNpjukmrx7Q9DkO5tFFsmNVxng==} dependencies: - '@docsearch/react': 3.2.1 - preact: 10.11.2 + '@docsearch/react': 3.1.0 + preact: 10.8.2 transitivePeerDependencies: - - '@algolia/client-search' - '@types/react' - react - react-dom - dev: true + dev: false - /@docsearch/react/3.2.1: - resolution: {integrity: sha512-EzTQ/y82s14IQC5XVestiK/kFFMe2aagoYFuTAIfIb/e+4FU7kSMKonRtLwsCiLQHmjvNQq+HO+33giJ5YVtaQ==} + /@docsearch/react/3.1.0: + resolution: {integrity: sha512-bjB6ExnZzf++5B7Tfoi6UXgNwoUnNOfZ1NyvnvPhWgCMy5V/biAtLL4o7owmZSYdAKeFSvZ5Lxm0is4su/dBWg==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' react: '>= 16.8.0 < 19.0.0' @@ -200,68 +182,10 @@ packages: react-dom: optional: true dependencies: - '@algolia/autocomplete-core': 1.7.1 - '@algolia/autocomplete-preset-algolia': 1.7.1_algoliasearch@4.14.2 - '@docsearch/css': 3.2.1 - algoliasearch: 4.14.2 - transitivePeerDependencies: - - '@algolia/client-search' - dev: true - - /@esbuild/android-arm/0.15.11: - resolution: {integrity: sha512-PzMcQLazLBkwDEkrNPi9AbjFt6+3I7HKbiYF2XtWQ7wItrHvEOeO3T8Am434zAozWtVP7lrTue1bEfc2nYWeCA==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64/0.15.11: - resolution: {integrity: sha512-geWp637tUhNmhL3Xgy4Bj703yXB9dqiLJe05lCUfjSFDrQf9C/8pArusyPUbUbPwlC/EAUjBw32sxuIl/11dZw==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@jridgewell/gen-mapping/0.3.2: - resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.17 - dev: true - - /@jridgewell/resolve-uri/3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array/1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/source-map/0.3.2: - resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} - dependencies: - '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.17 - dev: true - - /@jridgewell/sourcemap-codec/1.4.14: - resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - dev: true - - /@jridgewell/trace-mapping/0.3.17: - resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true + '@algolia/autocomplete-core': 1.6.3 + '@docsearch/css': 3.1.0 + algoliasearch: 4.13.1 + dev: false /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -284,6 +208,23 @@ packages: fastq: 1.13.0 dev: false + /@overtrue/easywechat-theme/1.0.5_vue@3.2.37: + resolution: {integrity: sha512-lAhge9nsO1rmfstWMd30qF8vWt3x2SuA1rc/i6FbctvGv7NzoN5p4Z4gIfxutcMiVJqdWYsCTFlTXH4bM5sPxg==} + dependencies: + '@docsearch/css': 3.1.0 + '@docsearch/js': 3.1.0 + '@vueuse/core': 7.7.1_vue@3.2.37 + body-scroll-lock: 3.1.5 + normalize.css: 8.0.1 + shiki: 0.9.15 + transitivePeerDependencies: + - '@types/react' + - '@vue/composition-api' + - react + - react-dom + - vue + dev: false + /@types/linkify-it/3.0.2: resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} dev: true @@ -299,136 +240,179 @@ packages: resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} dev: true - /@types/node/16.11.65: - resolution: {integrity: sha512-Vfz7wGMOr4jbQGiQHVJm8VjeQwM9Ya7mHe9LtQ264/Epf5n1KiZShOFqk++nBzw6a/ubgYdB9Od7P+MH/LjoWw==} + /@types/node/16.11.41: + resolution: {integrity: sha512-mqoYK2TnVjdkGk8qXAVGc/x9nSaTpSrFaGFm43BUH3IdoBV0nta6hYaGmdOvIMlbHJbUEVen3gvwpwovAZKNdQ==} dev: true - /@types/web-bluetooth/0.0.15: - resolution: {integrity: sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA==} - dev: true + /@types/web-bluetooth/0.0.14: + resolution: {integrity: sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==} + dev: false - /@vitejs/plugin-vue/3.1.2_vite@3.1.8+vue@3.2.41: - resolution: {integrity: sha512-3zxKNlvA3oNaKDYX0NBclgxTQ1xaFdL7PzwF6zj9tGFziKwmBa3Q/6XcJQxudlT81WxDjEhHmevvIC4Orc1LhQ==} - engines: {node: ^14.18.0 || >=16.0.0} + /@vitejs/plugin-vue/2.3.3_vite@2.9.12+vue@3.2.37: + resolution: {integrity: sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==} + engines: {node: '>=12.0.0'} peerDependencies: - vite: ^3.0.0 + vite: ^2.5.10 vue: ^3.2.25 dependencies: - vite: 3.1.8_terser@5.15.1 - vue: 3.2.41 - dev: true + vite: 2.9.12 + vue: 3.2.37 + dev: false - /@vue/compiler-core/3.2.41: - resolution: {integrity: sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==} + /@vue/compiler-core/3.2.37: + resolution: {integrity: sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg==} dependencies: - '@babel/parser': 7.19.4 - '@vue/shared': 3.2.41 + '@babel/parser': 7.18.5 + '@vue/shared': 3.2.37 estree-walker: 2.0.2 source-map: 0.6.1 - dev: true + dev: false - /@vue/compiler-dom/3.2.41: - resolution: {integrity: sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==} + /@vue/compiler-dom/3.2.37: + resolution: {integrity: sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ==} dependencies: - '@vue/compiler-core': 3.2.41 - '@vue/shared': 3.2.41 - dev: true + '@vue/compiler-core': 3.2.37 + '@vue/shared': 3.2.37 + dev: false - /@vue/compiler-sfc/3.2.41: - resolution: {integrity: sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==} + /@vue/compiler-sfc/3.2.37: + resolution: {integrity: sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==} dependencies: - '@babel/parser': 7.19.4 - '@vue/compiler-core': 3.2.41 - '@vue/compiler-dom': 3.2.41 - '@vue/compiler-ssr': 3.2.41 - '@vue/reactivity-transform': 3.2.41 - '@vue/shared': 3.2.41 + '@babel/parser': 7.18.5 + '@vue/compiler-core': 3.2.37 + '@vue/compiler-dom': 3.2.37 + '@vue/compiler-ssr': 3.2.37 + '@vue/reactivity-transform': 3.2.37 + '@vue/shared': 3.2.37 estree-walker: 2.0.2 magic-string: 0.25.9 - postcss: 8.4.18 + postcss: 8.4.14 source-map: 0.6.1 - dev: true + dev: false - /@vue/compiler-ssr/3.2.41: - resolution: {integrity: sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==} + /@vue/compiler-ssr/3.2.37: + resolution: {integrity: sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw==} dependencies: - '@vue/compiler-dom': 3.2.41 - '@vue/shared': 3.2.41 - dev: true + '@vue/compiler-dom': 3.2.37 + '@vue/shared': 3.2.37 + dev: false - /@vue/devtools-api/6.4.4: - resolution: {integrity: sha512-Ku31WzpOV/8cruFaXaEZKF81WkNnvCSlBY4eOGtz5WMSdJvX1v1WWlSMGZeqUwPtQ27ZZz7B62erEMq8JDjcXw==} - dev: true + /@vue/devtools-api/6.1.4: + resolution: {integrity: sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==} + dev: false - /@vue/reactivity-transform/3.2.41: - resolution: {integrity: sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==} + /@vue/reactivity-transform/3.2.37: + resolution: {integrity: sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg==} dependencies: - '@babel/parser': 7.19.4 - '@vue/compiler-core': 3.2.41 - '@vue/shared': 3.2.41 + '@babel/parser': 7.18.5 + '@vue/compiler-core': 3.2.37 + '@vue/shared': 3.2.37 estree-walker: 2.0.2 magic-string: 0.25.9 - dev: true + dev: false - /@vue/reactivity/3.2.41: - resolution: {integrity: sha512-9JvCnlj8uc5xRiQGZ28MKGjuCoPhhTwcoAdv3o31+cfGgonwdPNuvqAXLhlzu4zwqavFEG5tvaoINQEfxz+l6g==} + /@vue/reactivity/3.2.37: + resolution: {integrity: sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A==} dependencies: - '@vue/shared': 3.2.41 - dev: true + '@vue/shared': 3.2.37 + dev: false - /@vue/runtime-core/3.2.41: - resolution: {integrity: sha512-0LBBRwqnI0p4FgIkO9q2aJBBTKDSjzhnxrxHYengkAF6dMOjeAIZFDADAlcf2h3GDALWnblbeprYYpItiulSVQ==} + /@vue/runtime-core/3.2.37: + resolution: {integrity: sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ==} dependencies: - '@vue/reactivity': 3.2.41 - '@vue/shared': 3.2.41 - dev: true + '@vue/reactivity': 3.2.37 + '@vue/shared': 3.2.37 + dev: false - /@vue/runtime-dom/3.2.41: - resolution: {integrity: sha512-U7zYuR1NVIP8BL6jmOqmapRAHovEFp7CSw4pR2FacqewXNGqZaRfHoNLQsqQvVQ8yuZNZtxSZy0FFyC70YXPpA==} + /@vue/runtime-dom/3.2.37: + resolution: {integrity: sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw==} dependencies: - '@vue/runtime-core': 3.2.41 - '@vue/shared': 3.2.41 - csstype: 2.6.21 - dev: true + '@vue/runtime-core': 3.2.37 + '@vue/shared': 3.2.37 + csstype: 2.6.20 + dev: false - /@vue/server-renderer/3.2.41_vue@3.2.41: - resolution: {integrity: sha512-7YHLkfJdTlsZTV0ae5sPwl9Gn/EGr2hrlbcS/8naXm2CDpnKUwC68i1wGlrYAfIgYWL7vUZwk2GkYLQH5CvFig==} + /@vue/server-renderer/3.2.37_vue@3.2.37: + resolution: {integrity: sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA==} peerDependencies: - vue: 3.2.41 + vue: 3.2.37 dependencies: - '@vue/compiler-ssr': 3.2.41 - '@vue/shared': 3.2.41 - vue: 3.2.41 - dev: true + '@vue/compiler-ssr': 3.2.37 + '@vue/shared': 3.2.37 + vue: 3.2.37 + dev: false - /@vue/shared/3.2.41: - resolution: {integrity: sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==} - dev: true + /@vue/shared/3.2.37: + resolution: {integrity: sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==} + dev: false - /@vueuse/core/9.3.0_vue@3.2.41: - resolution: {integrity: sha512-64Rna8IQDWpdrJxgitDg7yv1yTp41ZmvV8zlLEylK4QQLWAhz1OFGZDPZ8bU4lwcGgbEJ2sGi2jrdNh4LttUSQ==} + /@vueuse/core/7.7.1_vue@3.2.37: + resolution: {integrity: sha512-PRRgbATMpoeUmkCEBtUeJgOwtew8s+4UsEd+Pm7MhkjL2ihCNrSqxNVtM6NFE4uP2sWnkGcZpCjPuNSxowJ1Ow==} + peerDependencies: + '@vue/composition-api': ^1.1.0 + vue: ^2.6.0 || ^3.2.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + vue: + optional: true dependencies: - '@types/web-bluetooth': 0.0.15 - '@vueuse/metadata': 9.3.0 - '@vueuse/shared': 9.3.0_vue@3.2.41 - vue-demi: 0.13.11_vue@3.2.41 - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: true + '@vueuse/shared': 7.7.1_vue@3.2.37 + vue: 3.2.37 + vue-demi: 0.13.1_vue@3.2.37 + dev: false - /@vueuse/metadata/9.3.0: - resolution: {integrity: sha512-GnnfjbzIPJIh9ngL9s9oGU1+Hx/h5/KFqTfJykzh/1xjaHkedV9g0MASpdmPZIP+ynNhKAcEfA6g5i8KXwtoMA==} - dev: true - - /@vueuse/shared/9.3.0_vue@3.2.41: - resolution: {integrity: sha512-caGUWLY0DpPC6l31KxeUy6vPVNA0yKxx81jFYLoMpyP6cF84FG5Dkf69DfSUqL57wX8JcUkJDMnQaQIZPWFEQQ==} + /@vueuse/core/8.7.5_vue@3.2.37: + resolution: {integrity: sha512-tqgzeZGoZcXzoit4kOGLWJibDMLp0vdm6ZO41SSUQhkhtrPhAg6dbIEPiahhUu6sZAmSYvVrZgEr5aKD51nrLA==} + peerDependencies: + '@vue/composition-api': ^1.1.0 + vue: ^2.6.0 || ^3.2.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + vue: + optional: true dependencies: - vue-demi: 0.13.11_vue@3.2.41 - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: true + '@types/web-bluetooth': 0.0.14 + '@vueuse/metadata': 8.7.5 + '@vueuse/shared': 8.7.5_vue@3.2.37 + vue: 3.2.37 + vue-demi: 0.13.1_vue@3.2.37 + dev: false + + /@vueuse/metadata/8.7.5: + resolution: {integrity: sha512-emJZKRQSaEnVqmlu39NpNp8iaW+bPC2kWykWoWOZMSlO/0QVEmO/rt8A5VhOEJTKLX3vwTevqbiRy9WJRwVOQg==} + dev: false + + /@vueuse/shared/7.7.1_vue@3.2.37: + resolution: {integrity: sha512-rN2qd22AUl7VdBxihagWyhUNHCyVk9IpvBTTfHoLH9G7rGE552X1f+zeCfehuno0zXif13jPw+icW/wn2a0rnQ==} + peerDependencies: + '@vue/composition-api': ^1.1.0 + vue: ^2.6.0 || ^3.2.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + vue: + optional: true + dependencies: + vue: 3.2.37 + vue-demi: 0.13.1_vue@3.2.37 + dev: false + + /@vueuse/shared/8.7.5_vue@3.2.37: + resolution: {integrity: sha512-THXPvMBFmg6Gf6AwRn/EdTh2mhqwjGsB2Yfp374LNQSQVKRHtnJ0I42bsZTn7nuEliBxqUrGQm/lN6qUHmhJLw==} + peerDependencies: + '@vue/composition-api': ^1.1.0 + vue: ^2.6.0 || ^3.2.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + vue: + optional: true + dependencies: + vue: 3.2.37 + vue-demi: 0.13.1_vue@3.2.37 + dev: false /acorn-node/1.8.2: resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==} @@ -449,30 +433,24 @@ packages: hasBin: true dev: false - /acorn/8.8.0: - resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /algoliasearch/4.14.2: - resolution: {integrity: sha512-ngbEQonGEmf8dyEh5f+uOIihv4176dgbuOZspiuhmTTBRBuzWu3KCGHre6uHj5YyuC7pNvQGzB6ZNJyZi0z+Sg==} + /algoliasearch/4.13.1: + resolution: {integrity: sha512-dtHUSE0caWTCE7liE1xaL+19AFf6kWEcyn76uhcitWpntqvicFHXKFoZe5JJcv9whQOTRM6+B8qJz6sFj+rDJA==} dependencies: - '@algolia/cache-browser-local-storage': 4.14.2 - '@algolia/cache-common': 4.14.2 - '@algolia/cache-in-memory': 4.14.2 - '@algolia/client-account': 4.14.2 - '@algolia/client-analytics': 4.14.2 - '@algolia/client-common': 4.14.2 - '@algolia/client-personalization': 4.14.2 - '@algolia/client-search': 4.14.2 - '@algolia/logger-common': 4.14.2 - '@algolia/logger-console': 4.14.2 - '@algolia/requester-browser-xhr': 4.14.2 - '@algolia/requester-common': 4.14.2 - '@algolia/requester-node-http': 4.14.2 - '@algolia/transporter': 4.14.2 - dev: true + '@algolia/cache-browser-local-storage': 4.13.1 + '@algolia/cache-common': 4.13.1 + '@algolia/cache-in-memory': 4.13.1 + '@algolia/client-account': 4.13.1 + '@algolia/client-analytics': 4.13.1 + '@algolia/client-common': 4.13.1 + '@algolia/client-personalization': 4.13.1 + '@algolia/client-search': 4.13.1 + '@algolia/logger-common': 4.13.1 + '@algolia/logger-console': 4.13.1 + '@algolia/requester-browser-xhr': 4.13.1 + '@algolia/requester-common': 4.13.1 + '@algolia/requester-node-http': 4.13.1 + '@algolia/transporter': 4.13.1 + dev: false /anymatch/3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} @@ -486,19 +464,19 @@ packages: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} dev: false - /autoprefixer/10.4.12_postcss@8.4.18: - resolution: {integrity: sha512-WrCGV9/b97Pa+jtwf5UGaRjgQIg7OK3D06GnoYoZNcG1Xb8Gt3EfuKjlhh9i/VtT16g6PYjZ69jdJ2g8FxSC4Q==} + /autoprefixer/10.4.7_postcss@8.4.14: + resolution: {integrity: sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: postcss: ^8.1.0 dependencies: - browserslist: 4.21.4 - caniuse-lite: 1.0.30001419 + browserslist: 4.21.0 + caniuse-lite: 1.0.30001359 fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 - postcss: 8.4.18 + postcss: 8.4.14 postcss-value-parser: 4.2.0 dev: false @@ -507,9 +485,13 @@ packages: engines: {node: '>=8'} dev: false + /body-scroll-lock/3.1.5: + resolution: {integrity: sha512-Yi1Xaml0EvNA0OYWxXiYNqY24AfWkbA6w5vxE7GWxtKfzIbZM+Qw+aSmkgsbWzbHiy/RCSkUZBplVxTA+E4jJg==} + dev: false + /body-scroll-lock/4.0.0-beta.0: resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==} - dev: true + dev: false /braces/3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} @@ -518,28 +500,24 @@ packages: fill-range: 7.0.1 dev: false - /browserslist/4.21.4: - resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} + /browserslist/4.21.0: + resolution: {integrity: sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001419 - electron-to-chromium: 1.4.283 - node-releases: 2.0.6 - update-browserslist-db: 1.0.10_browserslist@4.21.4 + caniuse-lite: 1.0.30001359 + electron-to-chromium: 1.4.169 + node-releases: 2.0.5 + update-browserslist-db: 1.0.4_browserslist@4.21.0 dev: false - /buffer-from/1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - /camelcase-css/2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} dev: false - /caniuse-lite/1.0.30001419: - resolution: {integrity: sha512-aFO1r+g6R7TW+PNQxKzjITwLOyDhVRLjW0LcwS/HCZGUUKTGNp9+IwLC4xyDSZBygVL/mxaFR3HIV6wEKQuSzw==} + /caniuse-lite/1.0.30001359: + resolution: {integrity: sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw==} dev: false /chokidar/3.5.3: @@ -569,22 +547,18 @@ packages: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: false - /commander/2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - /cssesc/3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true dev: false - /csstype/2.6.21: - resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} - dev: true + /csstype/2.6.20: + resolution: {integrity: sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==} + dev: false - /defined/1.0.1: - resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} + /defined/1.0.0: + resolution: {integrity: sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=} dev: false /delegate/3.2.0: @@ -597,8 +571,8 @@ packages: hasBin: true dependencies: acorn-node: 1.8.2 - defined: 1.0.1 - minimist: 1.2.7 + defined: 1.0.0 + minimist: 1.2.6 dev: false /didyoumean/1.2.2: @@ -613,219 +587,217 @@ packages: resolution: {integrity: sha1-uQvcM2Bc7+ZSuEFucB95v27vzjI=} dev: false - /electron-to-chromium/1.4.283: - resolution: {integrity: sha512-g6RQ9zCOV+U5QVHW9OpFR7rdk/V7xfopNXnyAamdpFgCHgZ1sjI8VuR1+zG2YG/TZk+tQ8mpNkug4P8FU0fuOA==} + /electron-to-chromium/1.4.169: + resolution: {integrity: sha512-Yb7UFva1sLlAaRyCkgoFF3qWvwZacFDtsGKi44rZsk8vnhL0DMhsUdhI4Dz9CCJQfftncDMGSI3AYiDtg8mD/w==} dev: false - /esbuild-android-64/0.15.11: - resolution: {integrity: sha512-rrwoXEiuI1kaw4k475NJpexs8GfJqQUKcD08VR8sKHmuW9RUuTR2VxcupVvHdiGh9ihxL9m3lpqB1kju92Ialw==} + /esbuild-android-64/0.14.47: + resolution: {integrity: sha512-R13Bd9+tqLVFndncMHssZrPWe6/0Kpv2/dt4aA69soX4PRxlzsVpCvoJeFE8sOEoeVEiBkI0myjlkDodXlHa0g==} engines: {node: '>=12'} cpu: [x64] os: [android] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-android-arm64/0.15.11: - resolution: {integrity: sha512-/hDubOg7BHOhUUsT8KUIU7GfZm5bihqssvqK5PfO4apag7YuObZRZSzViyEKcFn2tPeHx7RKbSBXvAopSHDZJQ==} + /esbuild-android-arm64/0.14.47: + resolution: {integrity: sha512-OkwOjj7ts4lBp/TL6hdd8HftIzOy/pdtbrNA4+0oVWgGG64HrdVzAF5gxtJufAPOsEjkyh1oIYvKAUinKKQRSQ==} engines: {node: '>=12'} cpu: [arm64] os: [android] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-darwin-64/0.15.11: - resolution: {integrity: sha512-1DqHD0ms3AhiwkKnjRUzmiW7JnaJJr5FKrPiR7xuyMwnjDqvNWDdMq4rKSD9OC0piFNK6n0LghsglNMe2MwJtA==} + /esbuild-darwin-64/0.14.47: + resolution: {integrity: sha512-R6oaW0y5/u6Eccti/TS6c/2c1xYTb1izwK3gajJwi4vIfNs1s8B1dQzI1UiC9T61YovOQVuePDcfqHLT3mUZJA==} engines: {node: '>=12'} cpu: [x64] os: [darwin] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-darwin-arm64/0.15.11: - resolution: {integrity: sha512-OMzhxSbS0lwwrW40HHjRCeVIJTURdXFA8c3GU30MlHKuPCcvWNUIKVucVBtNpJySXmbkQMDJdJNrXzNDyvoqvQ==} + /esbuild-darwin-arm64/0.14.47: + resolution: {integrity: sha512-seCmearlQyvdvM/noz1L9+qblC5vcBrhUaOoLEDDoLInF/VQ9IkobGiLlyTPYP5dW1YD4LXhtBgOyevoIHGGnw==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-freebsd-64/0.15.11: - resolution: {integrity: sha512-8dKP26r0/Qyez8nTCwpq60QbuYKOeBygdgOAWGCRalunyeqWRoSZj9TQjPDnTTI9joxd3QYw3UhVZTKxO9QdRg==} + /esbuild-freebsd-64/0.14.47: + resolution: {integrity: sha512-ZH8K2Q8/Ux5kXXvQMDsJcxvkIwut69KVrYQhza/ptkW50DC089bCVrJZZ3sKzIoOx+YPTrmsZvqeZERjyYrlvQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-freebsd-arm64/0.15.11: - resolution: {integrity: sha512-aSGiODiukLGGnSg/O9+cGO2QxEacrdCtCawehkWYTt5VX1ni2b9KoxpHCT9h9Y6wGqNHmXFnB47RRJ8BIqZgmQ==} + /esbuild-freebsd-arm64/0.14.47: + resolution: {integrity: sha512-ZJMQAJQsIOhn3XTm7MPQfCzEu5b9STNC+s90zMWe2afy9EwnHV7Ov7ohEMv2lyWlc2pjqLW8QJnz2r0KZmeAEQ==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-linux-32/0.15.11: - resolution: {integrity: sha512-lsrAfdyJBGx+6aHIQmgqUonEzKYeBnyfJPkT6N2dOf1RoXYYV1BkWB6G02tjsrz1d5wZzaTc3cF+TKmuTo/ZwA==} + /esbuild-linux-32/0.14.47: + resolution: {integrity: sha512-FxZOCKoEDPRYvq300lsWCTv1kcHgiiZfNrPtEhFAiqD7QZaXrad8LxyJ8fXGcWzIFzRiYZVtB3ttvITBvAFhKw==} engines: {node: '>=12'} cpu: [ia32] os: [linux] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-linux-64/0.15.11: - resolution: {integrity: sha512-Y2Rh+PcyVhQqXKBTacPCltINN3uIw2xC+dsvLANJ1SpK5NJUtxv8+rqWpjmBgaNWKQT1/uGpMmA9olALy9PLVA==} + /esbuild-linux-64/0.14.47: + resolution: {integrity: sha512-nFNOk9vWVfvWYF9YNYksZptgQAdstnDCMtR6m42l5Wfugbzu11VpMCY9XrD4yFxvPo9zmzcoUL/88y0lfJZJJw==} engines: {node: '>=12'} cpu: [x64] os: [linux] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-linux-arm/0.15.11: - resolution: {integrity: sha512-TJllTVk5aSyqPFvvcHTvf6Wu1ZKhWpJ/qNmZO8LL/XeB+LXCclm7HQHNEIz6MT7IX8PmlC1BZYrOiw2sXSB95A==} + /esbuild-linux-arm/0.14.47: + resolution: {integrity: sha512-ZGE1Bqg/gPRXrBpgpvH81tQHpiaGxa8c9Rx/XOylkIl2ypLuOcawXEAo8ls+5DFCcRGt/o3sV+PzpAFZobOsmA==} engines: {node: '>=12'} cpu: [arm] os: [linux] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-linux-arm64/0.15.11: - resolution: {integrity: sha512-uhcXiTwTmD4OpxJu3xC5TzAAw6Wzf9O1XGWL448EE9bqGjgV1j+oK3lIHAfsHnuIn8K4nDW8yjX0Sv5S++oRuw==} + /esbuild-linux-arm64/0.14.47: + resolution: {integrity: sha512-ywfme6HVrhWcevzmsufjd4iT3PxTfCX9HOdxA7Hd+/ZM23Y9nXeb+vG6AyA6jgq/JovkcqRHcL9XwRNpWG6XRw==} engines: {node: '>=12'} cpu: [arm64] os: [linux] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-linux-mips64le/0.15.11: - resolution: {integrity: sha512-WD61y/R1M4BLe4gxXRypoQ0Ci+Vjf714QYzcPNkiYv5I8K8WDz2ZR8Bm6cqKxd6rD+e/rZgPDbhQ9PCf7TMHmA==} + /esbuild-linux-mips64le/0.14.47: + resolution: {integrity: sha512-mg3D8YndZ1LvUiEdDYR3OsmeyAew4MA/dvaEJxvyygahWmpv1SlEEnhEZlhPokjsUMfRagzsEF/d/2XF+kTQGg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-linux-ppc64le/0.15.11: - resolution: {integrity: sha512-JVleZS9oPVLTlBhPTWgOwxFWU/wMUdlBwTbGA4GF8c38sLbS13cupj+C8bLq929jU7EMWry4SaL+tKGIaTlqKg==} + /esbuild-linux-ppc64le/0.14.47: + resolution: {integrity: sha512-WER+f3+szmnZiWoK6AsrTKGoJoErG2LlauSmk73LEZFQ/iWC+KhhDsOkn1xBUpzXWsxN9THmQFltLoaFEH8F8w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-linux-riscv64/0.15.11: - resolution: {integrity: sha512-9aLIalZ2HFHIOZpmVU11sEAS9F8TnHw49daEjcgMpBXHFF57VuT9f9/9LKJhw781Gda0P9jDkuCWJ0tFbErvJw==} + /esbuild-linux-riscv64/0.14.47: + resolution: {integrity: sha512-1fI6bP3A3rvI9BsaaXbMoaOjLE3lVkJtLxsgLHqlBhLlBVY7UqffWBvkrX/9zfPhhVMd9ZRFiaqXnB1T7BsL2g==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-linux-s390x/0.15.11: - resolution: {integrity: sha512-sZHtiXXOKsLI3XGBGoYO4qKBzJlb8xNsWmvFiwFMHFzA4AXgDP1KDp7Dawe9C2pavTRBDvl+Ok4n/DHQ59oaTg==} + /esbuild-linux-s390x/0.14.47: + resolution: {integrity: sha512-eZrWzy0xFAhki1CWRGnhsHVz7IlSKX6yT2tj2Eg8lhAwlRE5E96Hsb0M1mPSE1dHGpt1QVwwVivXIAacF/G6mw==} engines: {node: '>=12'} cpu: [s390x] os: [linux] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-netbsd-64/0.15.11: - resolution: {integrity: sha512-hUC9yN06K9sg7ju4Vgu9ChAPdsEgtcrcLfyNT5IKwKyfpLvKUwCMZSdF+gRD3WpyZelgTQfJ+pDx5XFbXTlB0A==} + /esbuild-netbsd-64/0.14.47: + resolution: {integrity: sha512-Qjdjr+KQQVH5Q2Q1r6HBYswFTToPpss3gqCiSw2Fpq/ua8+eXSQyAMG+UvULPqXceOwpnPo4smyZyHdlkcPppQ==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-openbsd-64/0.15.11: - resolution: {integrity: sha512-0bBo9SQR4t66Wd91LGMAqmWorzO0TTzVjYiifwoFtel8luFeXuPThQnEm5ztN4g0fnvcp7AnUPPzS/Depf17wQ==} + /esbuild-openbsd-64/0.14.47: + resolution: {integrity: sha512-QpgN8ofL7B9z8g5zZqJE+eFvD1LehRlxr25PBkjyyasakm4599iroUpaj96rdqRlO2ShuyqwJdr+oNqWwTUmQw==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-sunos-64/0.15.11: - resolution: {integrity: sha512-EuBdTGlsMTjEl1sQnBX2jfygy7iR6CKfvOzi+gEOfhDqbHXsmY1dcpbVtcwHAg9/2yUZSfMJHMAgf1z8M4yyyw==} + /esbuild-sunos-64/0.14.47: + resolution: {integrity: sha512-uOeSgLUwukLioAJOiGYm3kNl+1wJjgJA8R671GYgcPgCx7QR73zfvYqXFFcIO93/nBdIbt5hd8RItqbbf3HtAQ==} engines: {node: '>=12'} cpu: [x64] os: [sunos] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-windows-32/0.15.11: - resolution: {integrity: sha512-O0/Wo1Wk6dc0rZSxkvGpmTNIycEznHmkObTFz2VHBhjPsO4ZpCgfGxNkCpz4AdAIeMczpTXt/8d5vdJNKEGC+Q==} + /esbuild-windows-32/0.14.47: + resolution: {integrity: sha512-H0fWsLTp2WBfKLBgwYT4OTfFly4Im/8B5f3ojDv1Kx//kiubVY0IQunP2Koc/fr/0wI7hj3IiBDbSrmKlrNgLQ==} engines: {node: '>=12'} cpu: [ia32] os: [win32] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-windows-64/0.15.11: - resolution: {integrity: sha512-x977Q4HhNjnHx00b4XLAnTtj5vfbdEvkxaQwC1Zh5AN8g5EX+izgZ6e5QgqJgpzyRNJqh4hkgIJF1pyy1be0mQ==} + /esbuild-windows-64/0.14.47: + resolution: {integrity: sha512-/Pk5jIEH34T68r8PweKRi77W49KwanZ8X6lr3vDAtOlH5EumPE4pBHqkCUdELanvsT14yMXLQ/C/8XPi1pAtkQ==} engines: {node: '>=12'} cpu: [x64] os: [win32] requiresBuild: true - dev: true + dev: false optional: true - /esbuild-windows-arm64/0.15.11: - resolution: {integrity: sha512-VwUHFACuBahrvntdcMKZteUZ9HaYrBRODoKe4tIWxguQRvvYoYb7iu5LrcRS/FQx8KPZNaa72zuqwVtHeXsITw==} + /esbuild-windows-arm64/0.14.47: + resolution: {integrity: sha512-HFSW2lnp62fl86/qPQlqw6asIwCnEsEoNIL1h2uVMgakddf+vUuMcCbtUY1i8sst7KkgHrVKCJQB33YhhOweCQ==} engines: {node: '>=12'} cpu: [arm64] os: [win32] requiresBuild: true - dev: true + dev: false optional: true - /esbuild/0.15.11: - resolution: {integrity: sha512-OgHGuhlfZ//mToxjte1D5iiiQgWfJ2GByVMwEC/IuoXsBGkuyK1+KrjYu0laSpnN/L1UmLUCv0s25vObdc1bVg==} + /esbuild/0.14.47: + resolution: {integrity: sha512-wI4ZiIfFxpkuxB8ju4MHrGwGLyp1+awEHAHVpx6w7a+1pmYIq8T9FGEVVwFo0iFierDoMj++Xq69GXWYn2EiwA==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.15.11 - '@esbuild/linux-loong64': 0.15.11 - esbuild-android-64: 0.15.11 - esbuild-android-arm64: 0.15.11 - esbuild-darwin-64: 0.15.11 - esbuild-darwin-arm64: 0.15.11 - esbuild-freebsd-64: 0.15.11 - esbuild-freebsd-arm64: 0.15.11 - esbuild-linux-32: 0.15.11 - esbuild-linux-64: 0.15.11 - esbuild-linux-arm: 0.15.11 - esbuild-linux-arm64: 0.15.11 - esbuild-linux-mips64le: 0.15.11 - esbuild-linux-ppc64le: 0.15.11 - esbuild-linux-riscv64: 0.15.11 - esbuild-linux-s390x: 0.15.11 - esbuild-netbsd-64: 0.15.11 - esbuild-openbsd-64: 0.15.11 - esbuild-sunos-64: 0.15.11 - esbuild-windows-32: 0.15.11 - esbuild-windows-64: 0.15.11 - esbuild-windows-arm64: 0.15.11 - dev: true + esbuild-android-64: 0.14.47 + esbuild-android-arm64: 0.14.47 + esbuild-darwin-64: 0.14.47 + esbuild-darwin-arm64: 0.14.47 + esbuild-freebsd-64: 0.14.47 + esbuild-freebsd-arm64: 0.14.47 + esbuild-linux-32: 0.14.47 + esbuild-linux-64: 0.14.47 + esbuild-linux-arm: 0.14.47 + esbuild-linux-arm64: 0.14.47 + esbuild-linux-mips64le: 0.14.47 + esbuild-linux-ppc64le: 0.14.47 + esbuild-linux-riscv64: 0.14.47 + esbuild-linux-s390x: 0.14.47 + esbuild-netbsd-64: 0.14.47 + esbuild-openbsd-64: 0.14.47 + esbuild-sunos-64: 0.14.47 + esbuild-windows-32: 0.14.47 + esbuild-windows-64: 0.14.47 + esbuild-windows-arm64: 0.14.47 + dev: false /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -834,10 +806,10 @@ packages: /estree-walker/2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true + dev: false - /fast-glob/3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + /fast-glob/3.2.11: + resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} engines: {node: '>=8.6.0'} dependencies: '@nodelib/fs.stat': 2.0.5 @@ -869,10 +841,12 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true + dev: false optional: true /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: false /glob-parent/5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -894,8 +868,8 @@ packages: delegate: 3.2.0 dev: false - /gsap/3.11.3: - resolution: {integrity: sha512-xc/iIJy+LWiMbRa4IdMtdnnKa/7PXEK6NNzV71gdOYUVeTZN7UWnLU0fB7Hi1iwiz4ZZoYkBZPPYGg+2+zzFHA==} + /gsap/3.10.4: + resolution: {integrity: sha512-6QatdkKxXCMfvCW4rM++0RqyLQAzFX5nwl3yHS0XPgkZBkiSEY3VZVbMltrdtsbER/xZonLtyHt684wRp4erlQ==} dev: false /has/1.0.3: @@ -903,6 +877,7 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 + dev: false /is-binary-path/2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} @@ -911,10 +886,11 @@ packages: binary-extensions: 2.2.0 dev: false - /is-core-module/2.10.0: - resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} + /is-core-module/2.9.0: + resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} dependencies: has: 1.0.3 + dev: false /is-extglob/2.1.1: resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} @@ -933,12 +909,12 @@ packages: engines: {node: '>=0.12.0'} dev: false - /jsonc-parser/3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - dev: true + /jsonc-parser/3.0.0: + resolution: {integrity: sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==} + dev: false - /lilconfig/2.0.6: - resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==} + /lilconfig/2.0.5: + resolution: {integrity: sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==} engines: {node: '>=10'} dev: false @@ -946,7 +922,7 @@ packages: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} dependencies: sourcemap-codec: 1.4.8 - dev: true + dev: false /merge2/1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -961,17 +937,18 @@ packages: picomatch: 2.3.1 dev: false - /minimist/1.2.7: - resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + /minimist/1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} dev: false /nanoid/3.3.4: resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + dev: false - /node-releases/2.0.6: - resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} + /node-releases/2.0.5: + resolution: {integrity: sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==} dev: false /normalize-path/3.0.0: @@ -984,6 +961,10 @@ packages: engines: {node: '>=0.10.0'} dev: false + /normalize.css/8.0.1: + resolution: {integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==} + dev: false + /object-hash/3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} @@ -991,9 +972,11 @@ packages: /path-parse/1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: false /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: false /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -1003,29 +986,31 @@ packages: /pify/2.3.0: resolution: {integrity: sha1-7RQaasBDqEnqWISY59yosVMw6Qw=} engines: {node: '>=0.10.0'} + dev: false - /postcss-import/14.1.0_postcss@8.4.18: + /postcss-import/14.1.0_postcss@8.4.14: resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==} engines: {node: '>=10.0.0'} peerDependencies: postcss: ^8.0.0 dependencies: - postcss: 8.4.18 + postcss: 8.4.14 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.1 + dev: false - /postcss-js/4.0.0_postcss@8.4.18: + /postcss-js/4.0.0_postcss@8.4.14: resolution: {integrity: sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.3.3 dependencies: camelcase-css: 2.0.1 - postcss: 8.4.18 + postcss: 8.4.14 dev: false - /postcss-load-config/3.1.4_postcss@8.4.18: + /postcss-load-config/3.1.4_postcss@8.4.14: resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} engines: {node: '>= 10'} peerDependencies: @@ -1037,18 +1022,18 @@ packages: ts-node: optional: true dependencies: - lilconfig: 2.0.6 - postcss: 8.4.18 + lilconfig: 2.0.5 + postcss: 8.4.14 yaml: 1.10.2 dev: false - /postcss-nested/5.0.6_postcss@8.4.18: + /postcss-nested/5.0.6_postcss@8.4.14: resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 dependencies: - postcss: 8.4.18 + postcss: 8.4.14 postcss-selector-parser: 6.0.10 dev: false @@ -1062,18 +1047,20 @@ packages: /postcss-value-parser/4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: false - /postcss/8.4.18: - resolution: {integrity: sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==} + /postcss/8.4.14: + resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.4 picocolors: 1.0.0 source-map-js: 1.0.2 + dev: false - /preact/10.11.2: - resolution: {integrity: sha512-skAwGDFmgxhq1DCBHke/9e12ewkhc7WYwjuhHB8HHS8zkdtITXLRmUMTeol2ldxvLwYtwbFeifZ9uDDWuyL4Iw==} - dev: true + /preact/10.8.2: + resolution: {integrity: sha512-AKGt0BsDSiAYzVS78jZ9qRwuorY2CoSZtf1iOC6gLb/3QyZt+fLT09aYJBjRc/BEcRc4j+j3ggERMdNE43i1LQ==} + dev: false /queue-microtask/1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -1088,6 +1075,7 @@ packages: resolution: {integrity: sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=} dependencies: pify: 2.3.0 + dev: false /readdirp/3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} @@ -1100,22 +1088,23 @@ packages: resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} hasBin: true dependencies: - is-core-module: 2.10.0 + is-core-module: 2.9.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + dev: false /reusify/1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} dev: false - /rollup/2.78.1: - resolution: {integrity: sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==} + /rollup/2.75.7: + resolution: {integrity: sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==} engines: {node: '>=10.0.0'} hasBin: true optionalDependencies: fsevents: 2.3.2 - dev: true + dev: false /run-parallel/1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1127,40 +1116,43 @@ packages: resolution: {integrity: sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=} dev: false - /shiki/0.11.1: - resolution: {integrity: sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==} + /shiki/0.10.1: + resolution: {integrity: sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==} dependencies: - jsonc-parser: 3.2.0 + jsonc-parser: 3.0.0 vscode-oniguruma: 1.6.2 - vscode-textmate: 6.0.0 - dev: true + vscode-textmate: 5.2.0 + dev: false + + /shiki/0.9.15: + resolution: {integrity: sha512-/Y0z9IzhJ8nD9nbceORCqu6NgT9X6I8Fk8c3SICHI5NbZRLdZYFaB233gwct9sU0vvSypyaL/qaKvzyQGJBZSw==} + dependencies: + jsonc-parser: 3.0.0 + vscode-oniguruma: 1.6.2 + vscode-textmate: 5.2.0 + dev: false /source-map-js/1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - - /source-map-support/0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true + dev: false /source-map/0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - dev: true + dev: false /sourcemap-codec/1.4.8: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} - dev: true + dev: false /supports-preserve-symlinks-flag/1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + dev: false - /tailwindcss/3.1.8: - resolution: {integrity: sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==} + /tailwindcss/3.1.4: + resolution: {integrity: sha512-NrxbFV4tYsga/hpWbRyUfIaBrNMXDxx5BsHgBS4v5tlyjf+sDsgBg5m9OxjrXIqAS/uR9kicxLKP+bEHI7BSeQ==} engines: {node: '>=12.13.0'} hasBin: true dependencies: @@ -1170,18 +1162,18 @@ packages: detective: 5.2.1 didyoumean: 1.2.2 dlv: 1.1.3 - fast-glob: 3.2.12 + fast-glob: 3.2.11 glob-parent: 6.0.2 is-glob: 4.0.3 - lilconfig: 2.0.6 + lilconfig: 2.0.5 normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.0.0 - postcss: 8.4.18 - postcss-import: 14.1.0_postcss@8.4.18 - postcss-js: 4.0.0_postcss@8.4.18 - postcss-load-config: 3.1.4_postcss@8.4.18 - postcss-nested: 5.0.6_postcss@8.4.18 + postcss: 8.4.14 + postcss-import: 14.1.0_postcss@8.4.14 + postcss-js: 4.0.0_postcss@8.4.14 + postcss-load-config: 3.1.4_postcss@8.4.14 + postcss-nested: 5.0.6_postcss@8.4.14 postcss-selector-parser: 6.0.10 postcss-value-parser: 4.2.0 quick-lru: 5.1.1 @@ -1190,17 +1182,6 @@ packages: - ts-node dev: false - /terser/5.15.1: - resolution: {integrity: sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.2 - acorn: 8.8.0 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - /tiny-emitter/2.1.0: resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} dev: false @@ -1208,7 +1189,7 @@ packages: /to-fast-properties/2.0.0: resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} engines: {node: '>=4'} - dev: true + dev: false /to-regex-range/5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} @@ -1217,13 +1198,13 @@ packages: is-number: 7.0.0 dev: false - /update-browserslist-db/1.0.10_browserslist@4.21.4: - resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + /update-browserslist-db/1.0.4_browserslist@4.21.0: + resolution: {integrity: sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' dependencies: - browserslist: 4.21.4 + browserslist: 4.21.0 escalade: 3.1.1 picocolors: 1.0.0 dev: false @@ -1232,15 +1213,14 @@ packages: resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} dev: false - /vite/3.1.8_terser@5.15.1: - resolution: {integrity: sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==} - engines: {node: ^14.18.0 || >=16.0.0} + /vite/2.9.12: + resolution: {integrity: sha512-suxC36dQo9Rq1qMB2qiRorNJtJAdxguu5TMvBHOc/F370KvqAe9t48vYp+/TbPKRNrMh/J55tOUmkuIqstZaew==} + engines: {node: '>=12.2.0'} hasBin: true peerDependencies: less: '*' sass: '*' stylus: '*' - terser: ^5.4.0 peerDependenciesMeta: less: optional: true @@ -1248,33 +1228,30 @@ packages: optional: true stylus: optional: true - terser: - optional: true dependencies: - esbuild: 0.15.11 - postcss: 8.4.18 + esbuild: 0.14.47 + postcss: 8.4.14 resolve: 1.22.1 - rollup: 2.78.1 - terser: 5.15.1 + rollup: 2.75.7 optionalDependencies: fsevents: 2.3.2 - dev: true + dev: false - /vitepress/1.0.0-alpha.21_terser@5.15.1: - resolution: {integrity: sha512-D/tkoDW16uUZ9pnWd28Kk1vX26zNiTml3m9oGbfx2pAfYg99PHd1GceZyEm4jZsJU0+n9S++1ctFxoQvsq376A==} + /vitepress/1.0.0-alpha.4: + resolution: {integrity: sha512-bOAA4KW6vYGlkbcrPLZLTKWTgXVroObU+o9xj9EENyEl6yg26WWvfN7DGA4BftjdM5O8nR93Z5khPQ3W/tFE7Q==} + engines: {node: '>=14.6.0'} hasBin: true dependencies: - '@docsearch/css': 3.2.1 - '@docsearch/js': 3.2.1 - '@vitejs/plugin-vue': 3.1.2_vite@3.1.8+vue@3.2.41 - '@vue/devtools-api': 6.4.4 - '@vueuse/core': 9.3.0_vue@3.2.41 + '@docsearch/css': 3.1.0 + '@docsearch/js': 3.1.0 + '@vitejs/plugin-vue': 2.3.3_vite@2.9.12+vue@3.2.37 + '@vue/devtools-api': 6.1.4 + '@vueuse/core': 8.7.5_vue@3.2.37 body-scroll-lock: 4.0.0-beta.0 - shiki: 0.11.1 - vite: 3.1.8_terser@5.15.1 - vue: 3.2.41 + shiki: 0.10.1 + vite: 2.9.12 + vue: 3.2.37 transitivePeerDependencies: - - '@algolia/client-search' - '@types/react' - '@vue/composition-api' - less @@ -1282,19 +1259,18 @@ packages: - react-dom - sass - stylus - - terser - dev: true + dev: false /vscode-oniguruma/1.6.2: resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==} - dev: true + dev: false - /vscode-textmate/6.0.0: - resolution: {integrity: sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==} - dev: true + /vscode-textmate/5.2.0: + resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==} + dev: false - /vue-demi/0.13.11_vue@3.2.41: - resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==} + /vue-demi/0.13.1_vue@3.2.37: + resolution: {integrity: sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==} engines: {node: '>=12'} hasBin: true requiresBuild: true @@ -1305,18 +1281,18 @@ packages: '@vue/composition-api': optional: true dependencies: - vue: 3.2.41 - dev: true + vue: 3.2.37 + dev: false - /vue/3.2.41: - resolution: {integrity: sha512-uuuvnrDXEeZ9VUPljgHkqB5IaVO8SxhPpqF2eWOukVrBnRBx2THPSGQBnVRt0GrIG1gvCmFXMGbd7FqcT1ixNQ==} + /vue/3.2.37: + resolution: {integrity: sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==} dependencies: - '@vue/compiler-dom': 3.2.41 - '@vue/compiler-sfc': 3.2.41 - '@vue/runtime-dom': 3.2.41 - '@vue/server-renderer': 3.2.41_vue@3.2.41 - '@vue/shared': 3.2.41 - dev: true + '@vue/compiler-dom': 3.2.37 + '@vue/compiler-sfc': 3.2.37 + '@vue/runtime-dom': 3.2.37 + '@vue/server-renderer': 3.2.37_vue@3.2.37 + '@vue/shared': 3.2.37 + dev: false /xtend/4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} diff --git a/vendor/w7corp/easywechat/docs/src/3.x/notice.md b/vendor/w7corp/easywechat/docs/src/3.x/notice.md index 5b871efbb..2ddfa1f6a 100755 --- a/vendor/w7corp/easywechat/docs/src/3.x/notice.md +++ b/vendor/w7corp/easywechat/docs/src/3.x/notice.md @@ -15,12 +15,12 @@ $notice = $app->notice; ### API -- `boolean setIndustry($industryId1, $industryId2)` 修改账号所属行业; -- `array getIndustry()` 返回所有支持的行业列表,用于做下拉选择行业可视化更新; -- `string addTemplate($shortId)` 添加模板并获取模板 ID; -- `collection send($message)` 发送模板消息, 返回消息 ID; -- `array getPrivateTemplates()` 获取所有模板列表; -- `array deletePrivateTemplate($templateId)` 删除指定 ID 的模板。 ++ `boolean setIndustry($industryId1, $industryId2)` 修改账号所属行业; ++ `array getIndustry()` 返回所有支持的行业列表,用于做下拉选择行业可视化更新; ++ `string addTemplate($shortId)` 添加模板并获取模板ID; ++ `collection send($message)` 发送模板消息, 返回消息ID; ++ `array getPrivateTemplates()` 获取所有模板列表; ++ `array deletePrivateTemplate($templateId)` 删除指定ID的模板。 非链接调用方法: @@ -93,48 +93,50 @@ var_dump($result); // } ``` +结果: + +![notice-demo](http://7u2jwa.com1.z0.glb.clouddn.com/QQ20160111-0@2x.png) + ## 模板数据 为了方便大家开发,我们拓展支持以下格式的模板数据,其它格式的数据可能会导致接口调用失败: - 所有数据项颜色一样的(这是方便的一种方式): - ```php - $data = array( - "first" => "恭喜你购买成功!", - "keynote1" => "巧克力", - "keynote2" => "39.8元", - "keynote3" => "2014年9月16日", - "remark" => "欢迎再次购买!", - ); - ``` - + ```php + $data = array( + "first" => "恭喜你购买成功!", + "keynote1" => "巧克力", + "keynote2" => "39.8元", + "keynote3" => "2014年9月16日", + "remark" => "欢迎再次购买!", + ); + ``` 默认颜色为'#173177', 你可以通过 `defaultColor($color)` 来修改 - 独立设置每个模板项颜色的: - - 简便型: + + 简便型: - ```php - $data = array( - "first" => array("恭喜你购买成功!", '#555555'), - "keynote1" => array("巧克力", "#336699"), - "keynote2" => array("39.8元", "#FF0000"), - "keynote3" => array("2014年9月16日", "#888888"), - "remark" => array("欢迎再次购买!", "#5599FF"), - ); - ``` + ```php + $data = array( + "first" => array("恭喜你购买成功!", '#555555'), + "keynote1" => array("巧克力", "#336699"), + "keynote2" => array("39.8元", "#FF0000"), + "keynote3" => array("2014年9月16日", "#888888"), + "remark" => array("欢迎再次购买!", "#5599FF"), + ); + ``` + + 复杂型(也是微信官方唯一支持的方式,估计没有人想这么用): - - 复杂型(也是微信官方唯一支持的方式,估计没有人想这么用): - - ```php - $data = array( - "first" => array("value" => "恭喜你购买成功!", "color" => '#555555'), - "keynote1" => array("value" => "巧克力", "color" => "#336699"), - "keynote2" => array("value" => "39.8元","color" => "#FF0000"), - "keynote3" => array("value" => "2014年9月16日", "color" => "#888888"), - "remark" => array("value" => "欢迎再次购买!", "color" => "#5599FF"), - ); - ``` + ```php + $data = array( + "first" => array("value" => "恭喜你购买成功!", "color" => '#555555'), + "keynote1" => array("value" => "巧克力", "color" => "#336699"), + "keynote2" => array("value" => "39.8元","color" => "#FF0000"), + "keynote3" => array("value" => "2014年9月16日", "color" => "#888888"), + "remark" => array("value" => "欢迎再次购买!", "color" => "#5599FF"), + ); + ``` 关于模板消息的使用请参考 [微信官方文档](http://mp.weixin.qq.com/wiki/) diff --git a/vendor/w7corp/easywechat/docs/src/3.x/oauth.md b/vendor/w7corp/easywechat/docs/src/3.x/oauth.md index ce54379e7..d724960fe 100755 --- a/vendor/w7corp/easywechat/docs/src/3.x/oauth.md +++ b/vendor/w7corp/easywechat/docs/src/3.x/oauth.md @@ -1,8 +1,9 @@ # 网页授权 + ## 关于 OAuth2.0 -OAuth 是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是 2.0 版。 +OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。 ``` @@ -25,7 +26,6 @@ OAuth 是一个关于授权(authorization)的开放网络标准,在全世 +--------+ +---------------+ OAuth 授权流程 ``` - > 摘自:[RFC 6749](https://datatracker.ietf.org/doc/rfc6749/?include_text=1) 步骤解释: @@ -59,8 +59,8 @@ OAuth 是一个关于授权(authorization)的开放网络标准,在全世 1. 用户尝试访问一个我们的业务页面,例如: `/user/profile` 2. 如果用户已经登录,则正常显示该页面 -3. 系统检查当前访问的用户并未登录(从 session 或者其它方式检查),则跳转到**跳转到微信授权服务器**(上面的两种中一种**授权 URL**),并告知微信授权服务器我的**回调 URL(redirect_uri=callback.php)**,此时用户看到蓝色的授权确认页面(`scope` 为 `snsapi_base` 时不显示) -4. 用户点击确定完成授权,浏览器跳转到**回调 URL**: `callback.php` 并带上 `code`: `?code=CODE&state=STATE`。 +2. 系统检查当前访问的用户并未登录(从 session 或者其它方式检查),则跳转到**跳转到微信授权服务器**(上面的两种中一种**授权 URL**),并告知微信授权服务器我的**回调URL(redirect_uri=callback.php)**,此时用户看到蓝色的授权确认页面(`scope` 为 `snsapi_base` 时不显示) +4. 用户点击确定完成授权,浏览器跳转到**回调URL**: `callback.php` 并带上 `code`: `?code=CODE&state=STATE`。 5. 在 `callback.php` 中得到 `code` 后,通过 `code` 再次向微信服务器请求得到 **网页授权 access_token** 与 `openid` 6. 你可以选择拿 `openid` 去请求 API 得到用户信息(可选) 7. 将用户信息写入 SESSION。 @@ -68,12 +68,12 @@ OAuth 是一个关于授权(authorization)的开放网络标准,在全世 > 看懵了?没事,使用 SDK,你不用管这么多。:smile: > -> 注意,上面的第 3 步:redirect_uri=callback.php 实际上我们会在 `callback.php` 后面还会带上授权目标页面 `user/profile`,所以完整的 `redirect_uri` 应该是下面的这样的 PHP 去拼出来:`'redirect_uri='.urlencode('callback.php?target=user/profile')` +> 注意,上面的第3步:redirect_uri=callback.php实际上我们会在 `callback.php` 后面还会带上授权目标页面 `user/profile`,所以完整的 `redirect_uri` 应该是下面的这样的PHP去拼出来:`'redirect_uri='.urlencode('callback.php?target=user/profile')` > 结果:redirect_uri=callback.php%3Ftarget%3Duser%2Fprofile ## 逻辑组成 -从上面我们所描述的授权流程来看,我们至少有 3 个页面: +从上面我们所描述的授权流程来看,我们至少有3个页面: 1. **业务页面**,也就是需要授权才能访问的页面。 2. **发起授权页**,此页面其实可以省略,可以做成一个中间件,全局检查未登录就发起授权。 @@ -87,7 +87,7 @@ OAuth 是一个关于授权(authorization)的开放网络标准,在全世 ## SDK 中 OAuth 模块的 API -在 SDK 中,我们使用名称为 `oauth` 的模块来完成授权服务,我们主要用到以下两个 API: + 在 SDK 中,我们使用名称为 `oauth` 的模块来完成授权服务,我们主要用到以下两个 API: ### 发起授权 @@ -96,7 +96,7 @@ $response = $app->oauth->scopes(['snsapi_userinfo']) ->redirect(); ``` -当你的应用是分布式架构且没有会话保持的情况下,你需要自行设置请求对象以实现会话共享。比如在 [Laravel](http://laravel.com) 框架中支持 Session 储存在 Redis 中,那么需要这样: +当你的应用是分布式架构且没有会话保持的情况下,你需要自行设置请求对象以实现会话共享。比如在 [Laravel](http://laravel.com) 框架中支持Session储存在Redis中,那么需要这样: ```php $response = $app->oauth->scopes(['snsapi_userinfo']) @@ -115,7 +115,7 @@ $response = $app->oauth->scopes(['snsapi_userinfo']) return $response; ``` -在有的框架 (比如 yii2) 中是直接 `echo` 或者 `$this->display()` 这种的时候,你就直接: +在有的框架 (比如yii2) 中是直接 `echo` 或者 `$this->display()` 这种的时候,你就直接: ```php $response->send(); // Laravel 里请使用:return $response; @@ -143,10 +143,10 @@ $user = $app->oauth->user(); ## 网页授权实例 -我们这里来用原生 PHP 写法举个例子,`oauth_callback` 是我们的授权回调 URL (未 urlencode 编码的 URL), `user/profile` 是我们需要授权才能访问的页面,它的 PHP 代码如下: +我们这里来用原生 PHP 写法举个例子,`oauth_callback` 是我们的授权回调URL (未urlencode编码的URL), `user/profile` 是我们需要授权才能访问的页面,它的 PHP 代码如下: ```php -// http://easywechat.com/user/profile +// http://easywechat.org/user/profile 'iPad mini 16G 白色', 'out_trade_no' => '1217752501201407033233368018',    'total_fee'       => 5388, // 单位:分 -    'notify_url'       => 'http://easywechat.com/order-notify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址 +    'notify_url'       => 'http://xxx.com/order-notify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址 'openid' => '当前用户的 openid', // trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识, // ... ]; @@ -74,7 +76,7 @@ $attributes = [ 'detail' => 'iPad mini 16G 白色', 'out_trade_no' => '1217752501201407033233368018', 'total_fee' => 5388, // 单位:分 - 'notify_url' => 'http://easywechat.com/order-notify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址 + 'notify_url' => 'http://xxx.com/order-notify', // 支付结果通知网址,如果不设置则会使用配置里的默认地址    'sub_openid'        => '当前用户的 openid', // 如果传入sub_openid, 请在实例化Application时, 同时传入$sub_app_id, $sub_merchant_id    // ... ]; @@ -83,7 +85,8 @@ $order = new Order($attributes); ``` -通知 url 必须为直接可访问的 url,不能携带参数。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action” + +通知url必须为直接可访问的url,不能携带参数。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action” ## 下单接口 @@ -110,7 +113,7 @@ if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){ ## 支付结果通知 -在用户成功支付后,微信服务器会向该 **订单中设置的回调 URL** 发起一个 POST 请求,请求的内容为一个 XML。里面包含了所有的详细信息,具体请参考: +在用户成功支付后,微信服务器会向该 **订单中设置的回调URL** 发起一个 POST 请求,请求的内容为一个 XML。里面包含了所有的详细信息,具体请参考: [支付结果通用通知](https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7) 在本 SDK 中处理回调真的再简单不过了,请求验证你就不用管了,SDK 已经为你做好了,你只需要关注业务即可: @@ -129,8 +132,8 @@ $response->send(); // Laravel 里请使用:return $response; 1. `handleNotify` 只接收一个 [`callable`](http://php.net/manual/zh/language.types.callable.php) 参数,通常用一个匿名函数即可。 2. 该匿名函数接收两个参数,这两个参数分别为: - - `$notify` 为封装了通知信息的 `EasyWeChat\Support\Collection` 对象,前面已经讲过这里就不赘述了,你可以以对象或者数组形式来读取通知内容,比如:`$notify->total_fee` 或者 `$notify['total_fee']`。 - - `$successful` 这个参数其实就是判断 **用户是否付款成功了**(result_code == 'SUCCESS') + - `$notify` 为封装了通知信息的 `EasyWeChat\Support\Collection` 对象,前面已经讲过这里就不赘述了,你可以以对象或者数组形式来读取通知内容,比如:`$notify->total_fee` 或者 `$notify['total_fee']`。 + - `$successful` 这个参数其实就是判断 **用户是否付款成功了**(result_code == 'SUCCESS') 3. 该函数返回值就是告诉微信 **“我是否处理完成”**,如果你返回一个 `false` 或者一个具体的错误消息,那么微信会在稍后再次继续通知你,直到你明确的告诉它:“我已经处理完成了”,在函数里 `return true;` 代表处理完成。 @@ -173,11 +176,12 @@ return $response; > 注意:请把 “支付成功与否” 与 “是否处理完成” 分开,它俩没有必然关系。 > 比如:微信通知你用户支付完成,但是支付失败了(result_code 为 'FAIL'),你应该**更新你的订单为支付失败**,但是要**告诉微信处理完成**。 -## 撤销订单 API + +## 撤销订单API 目前只有 **刷卡支付** 有此功能。 -> 调用支付接口后请勿立即调用撤销订单 API,建议支付后至少 15s 后再调用撤销订单接口。 +> 调用支付接口后请勿立即调用撤销订单API,建议支付后至少15s后再调用撤销订单接口。 ```php $orderNo = "商户系统内部的订单号(out_trade_no)"; @@ -192,16 +196,17 @@ $orderNo = "微信的订单号(transaction_id)"; $payment->reverseByTransactionId($orderNo); ``` + ## 查询订单 该接口提供所有微信支付订单的查询,商户可以通过该接口主动查询订单状态,完成下一步的业务逻辑。 需要调用查询接口的情况: -- 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知; -- 调用支付接口后,返回系统错误或未知交易状态情况; -- 调用被扫支付 API,返回 USERPAYING 的状态; -- 调用关单或撤销接口 API 之前,需确认支付状态; + - 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知; + - 调用支付接口后,返回系统错误或未知交易状态情况; + - 调用被扫支付API,返回USERPAYING的状态; + - 调用关单或撤销接口API之前,需确认支付状态; ```php $orderNo = "商户系统内部的订单号(out_trade_no)"; @@ -218,7 +223,7 @@ $payment->queryByTransactionId($orderNo); ## 关闭订单 -> 注意:订单生成后不能马上调用关单接口,最短调用时间间隔为 5 分钟。 +> 注意:订单生成后不能马上调用关单接口,最短调用时间间隔为5分钟。 ```php $orderNo = "商户系统内部的订单号(out_trade_no)"; @@ -268,7 +273,7 @@ $result = $payment->refundByTransactionId($transactionId, $refundNo, 100, 80, 19 ## 查询退款 -提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款 20 分钟内到账,银行卡支付的退款 3 个工作日后重新查询退款状态。 +提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。 ```php $result = $payment->queryRefund($outTradeNo); @@ -294,10 +299,10 @@ file_put_contents('YOUR/PATH/TO/bill-20140603.csv', $bill); 第二个参数为类型: -- **ALL**:返回当日所有订单信息(默认值) -- **SUCCESS**:返回当日成功支付的订单 -- **REFUND**:返回当日退款订单 -- **REVOKED**:已撤销的订单 + - **ALL**:返回当日所有订单信息(默认值) + - **SUCCESS**:返回当日成功支付的订单 + - **REFUND**:返回当日退款订单 + - **REVOKED**:已撤销的订单 ## 测速上报 @@ -315,10 +320,10 @@ $payment->report($api, $timeConsuming, $resultCode, $returnCode, [ ## 转换短链接 ```php -$shortUrl = $payment->urlShorten('http://easywechat.com'); +$shortUrl = $payment->urlShorten('http://easywechat.org'); ``` -## 授权码查询 OPENID 接口 +## 授权码查询OPENID接口 ```php $response = $payment->authCodeToOpenId($authCode); @@ -331,47 +336,47 @@ $response->openid; 1. WeixinJSBridge: - ```php - $json = $payment->configForPayment($prepayId); // 返回 json 字符串,如果想返回数组,传第二个参数 false - ``` + ```php + $json = $payment->configForPayment($prepayId); // 返回 json 字符串,如果想返回数组,传第二个参数 false + ``` - javascript: + javascript: - ```js - ... - WeixinJSBridge.invoke( - 'getBrandWCPayRequest', , - function(res){ - if(res.err_msg == "get_brand_wcpay_request:ok" ) { - // 使用以上方式判断前端返回,微信团队郑重提示: - // res.err_msg将在用户支付成功后返回 - // ok,但并不保证它绝对可靠。 - } - } - ); - ... - ``` + ```js + ... + WeixinJSBridge.invoke( + 'getBrandWCPayRequest', , + function(res){ + if(res.err_msg == "get_brand_wcpay_request:ok" ) { + // 使用以上方式判断前端返回,微信团队郑重提示: + // res.err_msg将在用户支付成功后返回 + // ok,但并不保证它绝对可靠。 + } + } + ); + ... + ``` 2. JSSDK: - ```php - $config = $payment->configForJSSDKPayment($prepayId); // 返回数组 - ``` + ```php + $config = $payment->configForJSSDKPayment($prepayId); // 返回数组 + ``` - javascript: + javascript: - ```js - wx.chooseWXPay({ - timestamp: , - nonceStr: '', - package: '', - signType: '', - paySign: '', // 支付签名 - success: function (res) { - // 支付成功后的回调函数 - } - }); - ``` + ```js + wx.chooseWXPay({ + timestamp: , + nonceStr: '', + package: '', + signType: '', + paySign: '', // 支付签名 + success: function (res) { + // 支付成功后的回调函数 + } + }); + ``` ## 生成共享收货地址 JS 配置 @@ -414,3 +419,4 @@ $config = $payment->configForAppPayment($prepayId); - https://github.com/Bacon/BaconQrCode - https://github.com/SimpleSoftwareIO/simple-qrcode (Bacon/BaconQrCode 的 Laravel 版本) - https://github.com/aferrandini/PHPQRCode + diff --git a/vendor/w7corp/easywechat/docs/src/3.x/poi.md b/vendor/w7corp/easywechat/docs/src/3.x/poi.md index fcb81f0a8..1e6bed091 100644 --- a/vendor/w7corp/easywechat/docs/src/3.x/poi.md +++ b/vendor/w7corp/easywechat/docs/src/3.x/poi.md @@ -1,5 +1,6 @@ # 门店 + ## 获取实例 ```php @@ -42,8 +43,8 @@ $info = array( "longitude" => 115.32375, "latitude" => 25.097486, "photo_list" => array( - array("photo_url" => "https://easywechat.com"), - array("photo_url" => "https://easywechat.com"), + array("photo_url" => "https://XXX.com"), + array("photo_url" => "https://XXX.com"), ), "recommend" => "麦辣鸡腿堡套餐,麦乐鸡,全家桶", "special" => "免费 wifi,外卖服务", @@ -55,15 +56,14 @@ $info = array( $result = $poi->create($info); // true or exception ``` -> 注意:新创建的门店在审核通过后,会以事件形式推送给商户填写的回调 URL +> 注意:新创建的门店在审核通过后,会以事件形式推送给商户填写的回调URL ## 获取指定门店信息 ```php $poi->get($poiId); ``` - -- `$poiId` 为门店 ID +- `$poiId` 为门店ID example: @@ -117,7 +117,7 @@ $pois = $poi->lists(0, 2);// 取2条记录 $poi->update($poiId, $data); ``` -- `$poiId` 为门店 ID +- `$poiId` 为门店ID - `$data` 需要更新的部分数据,**若有填写内容则为覆盖更新,若无内容则视为不 修改,维持原有内容。photo_list 字段为全列表覆盖,若需要增加图片,需将之前图片同样放入 list 中,在其后增加新增图片。如:已有 A、B、C 三张图片,又要增加 D、E 两张图,则需要调 用该接口,photo_list 传入 A、B、C、D、E 五张图片的链接。** example: @@ -149,6 +149,6 @@ $poi->delete(271262077);// true or exception - `invalid categories` 分类不合法,必须严格按照附表的分类填写 - `invalid photo url` 图片 url 不合法,必须使用接口 1 的图片上传 接口所获取的 url - `poi audit state must be approved` 门店状态必须未审核通过 -- `invalid poiid` poi_id 不正确 -- `invalid args` 参数不正确,请检查 json 字段 -- `system error` 系统错误,请稍后重试 +- `invalid poiid` poi_id 不正确 +- `invalid args` 参数不正确,请检查 json 字段 +- `system error` 系统错误,请稍后重试 \ No newline at end of file diff --git a/vendor/w7corp/easywechat/docs/src/3.x/roadmap.md b/vendor/w7corp/easywechat/docs/src/3.x/roadmap.md index 238dea5ec..46cde9e48 100755 --- a/vendor/w7corp/easywechat/docs/src/3.x/roadmap.md +++ b/vendor/w7corp/easywechat/docs/src/3.x/roadmap.md @@ -1,5 +1,6 @@ # 路线图 + ## 3.1 - 微信小店 @@ -10,12 +11,12 @@ - 全新的架构,更清晰的模块拆分 - Debug 优化,便于快速定位问题 -- 统一返回微信 API 原值,以 Collection 类装载,便于便捷操作 +- 统一返回微信API原值,以 Collection 类装载,便于便捷操作 - 大量模块重写 - 全新的支付模块 - 多类型缓存系统 - 新的命名空间:EasyWeChat -- 专属网站与更清晰与文档:http://easywechat.com +- 专属网站与更清晰与文档:http://easywechat.org ## 2.1 diff --git a/vendor/w7corp/easywechat/docs/src/3.x/tutorial.md b/vendor/w7corp/easywechat/docs/src/3.x/tutorial.md index cca31c52e..0e5192df0 100755 --- a/vendor/w7corp/easywechat/docs/src/3.x/tutorial.md +++ b/vendor/w7corp/easywechat/docs/src/3.x/tutorial.md @@ -1,6 +1,7 @@ # 快速开始 -在我们已经安装完成后,即可很快的开始使用它了,当然你还是有必要明白 PHP 基本知识,如命名空间等,我这里就不赘述了。 + +在我们已经安装完成后,即可很快的开始使用它了,当然你还是有必要明白PHP基本知识,如命名空间等,我这里就不赘述了。 我们以完成服务器端验证与接收响应用户发送的消息为例来演示,首先你有必要了解一下微信交互的运行流程: @@ -24,7 +25,7 @@ 考虑到这些,我已经把验证这一步给封装到 SDK 里了,你可以完全忽略这一步。 -下面我们来配置一个基本的服务端,这里假设我们自己的服务器域名叫 `easywechat.com`,我们在服务器上准备这么一个文件`server.php`: +下面我们来配置一个基本的服务端,这里假设我们自己的服务器域名叫 `easywechat.org`,我们在服务器上准备这么一个文件`server.php`: // server.php @@ -90,17 +91,20 @@ $response->send(); // Laravel 里请使用:return $response; 最后这一行我有必要详细讲一下: -> 1. 我们的 `$app->server->serve()` 就是执行服务端业务了,那么它的返回值呢,是一个 `Symfony\Component\HttpFoundation\Response` 实例。 -> 2. 我这里是直接调用了它的 `send()` 方法,它就是直接输出了,我们在一些框架就不能直接输出了,那你就直接拿到 Response 实例后做相应的操作即可,比如 Laravel 里你就可以直接 `return $app->server->serve();` + +>1. 我们的 `$app->server->serve()` 就是执行服务端业务了,那么它的返回值呢,是一个 `Symfony\Component\HttpFoundation\Response` 实例。 +>2. 我这里是直接调用了它的 `send()` 方法,它就是直接输出了,我们在一些框架就不能直接输出了,那你就直接拿到 Response 实例后做相应的操作即可,比如 Laravel 里你就可以直接 `return $app->server->serve();` + OK, 有了上面的代码,那么请你按 **[微信官方的接入指引](http://mp.weixin.qq.com/wiki/17/2d4265491f12608cd170a95559800f2d.html)** 操作,并相应修改上面的 `$options` 的配置。 -> URL 就是我们的 `http://easywechat.com/server.php`,这里我是举例哦,你可不要填写我的域名。 +> URL 就是我们的 `http://easywechat.org/server.php`,这里我是举例哦,你可不要填写我的域名。 -这样,点击提交验证就 OK 了。 +这样,点击提交验证就OK了。 > :heart: 请一定要将微信后台的开发者模式 “**启用**” !!!!!!看到红色 “**停用**” 才真正的是启用了。 + ## 接收 & 回复用户消息 那服务端验证通过了,我们就来试一下接收消息吧。 @@ -133,41 +137,42 @@ $response->send(); // Laravel 里请使用:return $response; 1. 所有的服务都通过主入口 `EasyWeChat\Foundation\Application` 类来获取: -```php -$app = new Application($options); + ```php + $app = new Application($options); -// services... -$server = $app->server; -$user = $app->user; -$oauth = $app->oauth; + // services... + $server = $app->server; + $user = $app->user; + $oauth = $app->oauth; -// ... js/menu/staff/material/qrcode/notice/stats... + // ... js/menu/staff/material/qrcode/notice/stats... -``` + ``` 2. 所有的 API 返回值均为 [`EasyWeChat\Support\Collection`](https://github.com/EasyWeChat/support/blob/master/src/Collection.php) 类,这个类是个什么东西呢? -它实现了一些 **[PHP 预定义接口](http://php.net/manual/zh/reserved.interfaces.php)**,比如:[`ArrayAccess`](http://php.net/manual/zh/class.arrayaccess.php)、[`Serializable`](http://php.net/manual/zh/class.serializable.php) 等。 + 它实现了一些 **[PHP预定义接口](http://php.net/manual/zh/reserved.interfaces.php)**,比如:[`ArrayAccess`](http://php.net/manual/zh/class.arrayaccess.php)、[`Serializable`](http://php.net/manual/zh/class.serializable.php) 等。 -有啥好处呢?它让我们操作起返回值来更方便,比如: + 有啥好处呢?它让我们操作起返回值来更方便,比如: -```php -$userService = $app->user; // 用户API + ```php + $userService = $app->user; // 用户API -$user = $userService->get($openId); + $user = $userService->get($openId); -// $user 便是一个 EasyWeChat\Support\Collection 实例 -$user['nickname']; -$user->nickname; -$user->get('nickname'); + // $user 便是一个 EasyWeChat\Support\Collection 实例 + $user['nickname']; + $user->nickname; + $user->get('nickname'); -//... -``` + //... + ``` -还有这些方便的操作:检查是否存在某个属性 `$user->has('email')`、元素个数 `$user->count()`,还有返回数组 `$user->toArray()` ,生成 JSON `$user->toJSON()` 等。 + 还有这些方便的操作:检查是否存在某个属性 `$user->has('email')`、元素个数 `$user->count()`,还有返回数组 `$user->toArray()` ,生成 JSON `$user->toJSON()` 等。 -## 最后 -希望你在使用本 SDK 的时候能忘记微信官方给你的痛苦,同时如果你发现 SDK 的不足,欢迎提交 PR 或者给我[提建议 & 报告问题](https://github.com/overtrue/wechat/issues)。 + ## 最后 -祝你生活愉快! + 希望你在使用本 SDK 的时候能忘记微信官方给你的痛苦,同时如果你发现 SDK 的不足,欢迎提交 PR 或者给我[提建议 & 报告问题](https://github.com/overtrue/wechat/issues)。 + + 祝你生活愉快! diff --git a/vendor/w7corp/easywechat/docs/src/4.x/client.md b/vendor/w7corp/easywechat/docs/src/4.x/client.md deleted file mode 100644 index 8c486d0d5..000000000 --- a/vendor/w7corp/easywechat/docs/src/4.x/client.md +++ /dev/null @@ -1,44 +0,0 @@ -# API 调用 - -该方法将 API 交由开发者自行调用,微信有部分新的接口4.x并未全部兼容支持,可以使用该方案去自行封装接口: - -例如URL Link接口 -```php -$api = $app->getClient(); - -$response = $api->httpPostJson('wxa/generate_urllink',[ - 'path' => 'pages/index/index', - 'is_expire' => true, - 'expire_type' => 1, - 'expire_interval' => 1 -]); -``` - -## 语法说明 - -```php -httpGet(string $uri, array $query = []) -httpPostJson(string $uri, array $data = [], array $query = []) -``` - - - -### GET - -```php -$response = $api->httpGet('/cgi-bin/user/list', [ - 'next_openid' => 'OPENID1', -]); -``` - -### POST - -```php -$response = $api->httpPostJson('/cgi-bin/user/info/updateremark', [ - "openid" => "oDF3iY9ffA-hqb2vVvbr7qxf6A0Q", - "remark" => "pangzi" -]); -``` - - - diff --git a/vendor/w7corp/easywechat/docs/src/4.x/official-account/accounts.md b/vendor/w7corp/easywechat/docs/src/4.x/official-account/accounts.md index c0f310457..bdbd37eb5 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/official-account/accounts.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/official-account/accounts.md @@ -12,7 +12,7 @@ 在微信公众平台的设置中,您可以将您帐号中平台的 `url` 设置为 `您的网址/?id=xxx`,如: ``` -http://easywechat.com/wechat?id=1 +http://www.easywechat.com/wechat?id=1 ``` 而在程序入口处,根据 `id` 查找对应帐号的 `appid` 和 其它信息来创建配置数组创建实例即可。 diff --git a/vendor/w7corp/easywechat/docs/src/4.x/official-account/card.md b/vendor/w7corp/easywechat/docs/src/4.x/official-account/card.md index 153a3c7d6..adaf3edc9 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/official-account/card.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/official-account/card.md @@ -37,7 +37,7 @@ $card->create($cardType = 'member_card', array $attributes); ```php [ @@ -109,7 +109,7 @@ $attributes = [ 'logo_url' => 'http://mmbiz.qpic.cn/mmbiz/2aJY6aCPatSeibYAyy7yct9zJXL9WsNVL4JdkTbBr184gNWS6nibcA75Hia9CqxicsqjYiaw2xuxYZiaibkmORS2oovdg/0', 'center_title' => '顶部居中按钮', 'center_sub_title' => '按钮下方的wording', - 'center_url' => 'http://easywechat.com', + 'center_url' => 'http://www.easywechat.com', 'custom_url_name' => '立即使用', 'custom_url' => 'http://www.qq.com', 'custom_url_sub_title' => '6个汉字tips', diff --git a/vendor/w7corp/easywechat/docs/src/4.x/official-account/material.md b/vendor/w7corp/easywechat/docs/src/4.x/official-account/material.md index d25098a4c..4ff1e2277 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/official-account/material.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/official-account/material.md @@ -84,7 +84,7 @@ $result = $app->material->updateArticle($mediaId, [ 'show_cover' => 1, // 是否在文章内容显示封面图片 'digest' => '这里是文章摘要', 'content' => '这里是文章内容,你可以放很长的内容', - 'source_url' => 'https://easywechat.com', + 'source_url' => 'https://www.easywechat.com', ]); // 指定更新多图文中的第 2 篇 @@ -230,7 +230,7 @@ $stats = $app->material->stats(); // } ``` -### 删除永久素材 +### 删除永久素材; ```php $app->material->delete($mediaId); diff --git a/vendor/w7corp/easywechat/docs/src/4.x/official-account/oauth.md b/vendor/w7corp/easywechat/docs/src/4.x/official-account/oauth.md index d8e235640..559ac6322 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/official-account/oauth.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/official-account/oauth.md @@ -133,7 +133,7 @@ $user = $app->oauth->user(); 我们这里来用原生 PHP 写法举个例子,`oauth_callback` 是我们的授权回调 URL (未 urlencode 编码的 URL), `user/profile` 是我们需要授权才能访问的页面,它的 PHP 代码如下: ```php -// http://easywechat.com/user/profile +// http://easywechat.org/user/profile 115.32375, "latitude" => 25.097486, "photo_list" => array( - array("photo_url" => "https://easywechat.com"), - array("photo_url" => "https://easywechat.com"), + array("photo_url" => "https://XXX.com"), + array("photo_url" => "https://XXX.com"), ), "recommend" => "麦辣鸡腿堡套餐,麦乐鸡,全家桶", "special" => "免费 wifi,外卖服务", diff --git a/vendor/w7corp/easywechat/docs/src/4.x/official-account/template_message.md b/vendor/w7corp/easywechat/docs/src/4.x/official-account/template_message.md index 9f6d31a21..b48d94cf3 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/official-account/template_message.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/official-account/template_message.md @@ -40,7 +40,7 @@ $app->template_message->deletePrivateTemplate($templateId); $app->template_message->send([ 'touser' => 'user-openid', 'template_id' => 'template-id', - 'url' => 'https://easywechat.com', + 'url' => 'https://easywechat.org', 'miniprogram' => [ 'appid' => 'xxxxxxx', 'pagepath' => 'pages/xxx', @@ -52,7 +52,6 @@ $app->template_message->send([ ], ]); ``` - > 如果 url 和 miniprogram 字段都传,会优先跳转小程序。 ## 发送一次性订阅消息 @@ -61,7 +60,7 @@ $app->template_message->send([ $app->template_message->sendSubscription([ 'touser' => 'user-openid', 'template_id' => 'template-id', - 'url' => 'https://easywechat.com', + 'url' => 'https://easywechat.org', 'scene' => 1000, 'data' => [ 'key1' => 'VALUE', diff --git a/vendor/w7corp/easywechat/docs/src/4.x/overview.md b/vendor/w7corp/easywechat/docs/src/4.x/overview.md index 2b7b5a367..0454d8126 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/overview.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/overview.md @@ -28,7 +28,7 @@ EasyWeChat 的安装非常简单,因为它是一个标准的 [Composer](https: ### 开始之前 -我们提供了视频教程: 当然,我还是建议你具备以下基础知识,否则可能没有那么快上手。 +我们提供了视频教程:https://www.easywechat.com/tutorials 当然,我还是建议你具备以下基础知识,否则可能没有那么快上手。 本 SDK 不是一个全新再造的东西,所以我不会从 0 开始教会你开发微信,你完全有必要在使用本 SDK 前做好以下工作: @@ -43,8 +43,8 @@ EasyWeChat 的安装非常简单,因为它是一个标准的 [Composer](https: 另外你有必要看一下以下的链接: -> - -> - +> - https://learnku.com/laravel/t/535/assertion-people-who-do-not-understand-the-wisdom-of-asking-questions-will-not-graduate-from-junior-programmers +> - http://laravel-china.github.io/php-the-right-way/ 如果你在群里问以下类似的问题,这真的是你没有做好上面的工作: diff --git a/vendor/w7corp/easywechat/docs/src/4.x/payment/order.md b/vendor/w7corp/easywechat/docs/src/4.x/payment/order.md index e5a7e8092..9997e4bc4 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/payment/order.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/payment/order.md @@ -57,7 +57,7 @@ $result = $app->order->unify([ 'plan_id' => 123,// 协议模板id 'contract_code' => 100001256,// 签约协议号 'contract_display_account' => '腾讯充值中心',// 签约用户的名称 - 'contract_notify_url' => 'http://easywechat.com/contract_notify' + 'contract_notify_url' => 'http://easywechat.org/contract_notify' ], $isContract); //$result: diff --git a/vendor/w7corp/easywechat/docs/src/4.x/payment/scan-pay.md b/vendor/w7corp/easywechat/docs/src/4.x/payment/scan-pay.md index a035356af..e7b0b7d78 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/payment/scan-pay.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/payment/scan-pay.md @@ -2,7 +2,7 @@ ### 模式一:先生成产品二维码,扫码下单后支付 -> 请务必先熟悉流程: +> 请务必先熟悉流程:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 #### 生成产品二维码内容 @@ -14,13 +14,13 @@ $content = $app->scheme($productId); // $productId 为你的产品/商品ID, 将 `$content` 生成二维码,SDK 并不内置二维码生成库,使用你熟悉的工具创建二维码即可,比如 PHP 部分有以下工具可以选择: -> - -> - -> - +> - https://github.com/endroid/qr-code +> - https://github.com/SimpleSoftwareIO/simple-qrcode +> - https://github.com/aferrandini/PHPQRCode #### 处理回调 -当用户扫码时,你的回调接口会收到一个通知,调用[统一下单接口](https://easywechat.com/docs/master/zh-CN/payment/order)创建订单后返回 `prepay_id`,你可以使用下面的代码处理扫码通知: +当用户扫码时,你的回调接口会收到一个通知,调用[统一下单接口](https://www.easywechat.com/docs/master/zh-CN/payment/order)创建订单后返回 `prepay_id`,你可以使用下面的代码处理扫码通知: ```php // 扫码支付通知接收第三个参数 `$alert`,如果触发该函数,会返回“业务错误”到微信服务器,触发 `$fail` 则返回“通信错误” @@ -39,15 +39,15 @@ $response = $app->handleScannedNotify(function ($message, $fail, $alert) use ($a $response->send(); ``` -用户在手机上付完钱以后,你会再收到**付款结果通知**,这时候请参考:[处理微信支付通知](https://easywechat.com/docs/master/zh-CN/payment/notify) 更新您的订单状态。 +用户在手机上付完钱以后,你会再收到**付款结果通知**,这时候请参考:[处理微信支付通知](https://www.easywechat.com/docs/master/zh-CN/payment/notify) 更新您的订单状态。 ### 模式二:先下单,生成订单后创建二维码 -> : +> :https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 #### 根据用户选购的商品生成订单 -调用[统一下单接口](https://easywechat.com/docs/master/zh-CN/payment/order)创建订单: +调用[统一下单接口](https://www.easywechat.com/docs/master/zh-CN/payment/order)创建订单: ```php $result = $app->order->unify([ @@ -67,4 +67,4 @@ $result = $app->order->unify([ #### 支付通知 -这种方式的通知就只有**付款结果通知**了,这时候请参考:[处理微信支付通知](https://easywechat.com/docs/master/zh-CN/payment/notify) 更新您的订单状态。 +这种方式的通知就只有**付款结果通知**了,这时候请参考:[处理微信支付通知](https://www.easywechat.com/docs/master/zh-CN/payment/notify) 更新您的订单状态。 diff --git a/vendor/w7corp/easywechat/docs/src/4.x/sidebar.js b/vendor/w7corp/easywechat/docs/src/4.x/sidebar.js index f24d5f3f8..c193ec941 100644 --- a/vendor/w7corp/easywechat/docs/src/4.x/sidebar.js +++ b/vendor/w7corp/easywechat/docs/src/4.x/sidebar.js @@ -195,13 +195,6 @@ exports = module.exports = [ { text: '模块替换', link: '/4.x/customize/replace-service.html' } ] }, - { - text: '通用', - collapsible: true, - items: [ - { text: 'API 调用', link: '/4.x/client.html' } - ] - }, { text: '其他', collapsible: true, diff --git a/vendor/w7corp/easywechat/docs/src/4.x/wework/external-contact.md b/vendor/w7corp/easywechat/docs/src/4.x/wework/external-contact.md index 4d7b8754b..d23196ade 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/wework/external-contact.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/wework/external-contact.md @@ -128,57 +128,6 @@ $configId = '42b34949e138eb6e027c123cba77fad7'; $app->contact_way->delete($configId); ``` -## 客户朋友圈 - -### 企业发表内容到客户的朋友圈 - -```php -$msg = [ - "text" => [ - "content" => "文本消息内容" - ], - "attachments" => [ - [ - "msgtype" => "image", - "image" => [ - "media_id" => "MEDIA_ID" - ] - ], - [ - "msgtype" => "video", - "video" => [ - "media_id" => "MEDIA_ID" - ] - ], - [ - "msgtype" => "link", - "link" => [ - "title" => "消息标题", - "url" => "https://example.link.com/path", - "media_id" => "MEDIA_ID" - ] - ] - ], - "visible_range" => [ - "sender_list" => [ - "user_list" => ["zhangshan","lisi"], - "department_list" => [2,3] - ], - "external_contact_list" => [ - "tag_list" => [ "etXXXXXXXXXX", "etYYYYYYYYYY"] - ] - ] -]; - -$app->external_contact_message->moments($msg); - -//{ -// "errcode":0, -// "errmsg":"ok", -// "jobid":"xxxx" -//} -``` - ## 消息管理 diff --git a/vendor/w7corp/easywechat/docs/src/4.x/wework/group-robot.md b/vendor/w7corp/easywechat/docs/src/4.x/wework/group-robot.md index 6d18af0bb..305d47291 100644 --- a/vendor/w7corp/easywechat/docs/src/4.x/wework/group-robot.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/wework/group-robot.md @@ -1,12 +1,11 @@ # 群机器人 ## 使用说明 - 使用前必须先在群组里面添加机器人,然后将 `Webhook 地址` 中的 `key` 取出来,作为示例中 `$groupKey` 的值。 -> Webhook 地址示例: +> Webhook 地址示例:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=`ab4f609a-3feb-427c-ae9d-b319ca712d36` -> 微信文档: +> 微信文档:https://work.weixin.qq.com/api/doc#90000/90136/91770 ## 发送文本类型消息 @@ -101,7 +100,7 @@ $items = [ new NewsItem([ 'title' => '中秋节礼品领取', 'description' => '今年中秋节公司有豪礼相送', - 'url' => 'https://easywechat.com', + 'url' => 'https://www.easywechat.com', 'image' => 'http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png', ]), diff --git a/vendor/w7corp/easywechat/docs/src/4.x/wework/media.md b/vendor/w7corp/easywechat/docs/src/4.x/wework/media.md index 0d94643a4..d115b6476 100755 --- a/vendor/w7corp/easywechat/docs/src/4.x/wework/media.md +++ b/vendor/w7corp/easywechat/docs/src/4.x/wework/media.md @@ -41,18 +41,4 @@ $app->media->uploadFile($path); ```php $app->media->get($mediaId); -``` - -## 上传附件资源 - -所有文件size必须大于5个字节 - -目前 商品图册只支持图片类型; 朋友圈只支持图片、视频类型 - -> - 图片(image):10MB,支持JPG,PNG格式,朋友圈类型图片不超过1440 x 1080 -> - 视频(video) :10MB,支持MP4格式,朋友圈类型视频时长不超过30秒 -> - 文件(file) :10MB - -```php -$app->media->uploadAttachmentResources($path, 'image', 1); ``` \ No newline at end of file diff --git a/vendor/w7corp/easywechat/docs/src/5.x/official-account/accounts.md b/vendor/w7corp/easywechat/docs/src/5.x/official-account/accounts.md index c0f310457..bdbd37eb5 100755 --- a/vendor/w7corp/easywechat/docs/src/5.x/official-account/accounts.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/official-account/accounts.md @@ -12,7 +12,7 @@ 在微信公众平台的设置中,您可以将您帐号中平台的 `url` 设置为 `您的网址/?id=xxx`,如: ``` -http://easywechat.com/wechat?id=1 +http://www.easywechat.com/wechat?id=1 ``` 而在程序入口处,根据 `id` 查找对应帐号的 `appid` 和 其它信息来创建配置数组创建实例即可。 diff --git a/vendor/w7corp/easywechat/docs/src/5.x/official-account/card.md b/vendor/w7corp/easywechat/docs/src/5.x/official-account/card.md index 153a3c7d6..adaf3edc9 100755 --- a/vendor/w7corp/easywechat/docs/src/5.x/official-account/card.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/official-account/card.md @@ -37,7 +37,7 @@ $card->create($cardType = 'member_card', array $attributes); ```php [ @@ -109,7 +109,7 @@ $attributes = [ 'logo_url' => 'http://mmbiz.qpic.cn/mmbiz/2aJY6aCPatSeibYAyy7yct9zJXL9WsNVL4JdkTbBr184gNWS6nibcA75Hia9CqxicsqjYiaw2xuxYZiaibkmORS2oovdg/0', 'center_title' => '顶部居中按钮', 'center_sub_title' => '按钮下方的wording', - 'center_url' => 'http://easywechat.com', + 'center_url' => 'http://www.easywechat.com', 'custom_url_name' => '立即使用', 'custom_url' => 'http://www.qq.com', 'custom_url_sub_title' => '6个汉字tips', diff --git a/vendor/w7corp/easywechat/docs/src/5.x/official-account/material.md b/vendor/w7corp/easywechat/docs/src/5.x/official-account/material.md index d25098a4c..4ff1e2277 100755 --- a/vendor/w7corp/easywechat/docs/src/5.x/official-account/material.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/official-account/material.md @@ -84,7 +84,7 @@ $result = $app->material->updateArticle($mediaId, [ 'show_cover' => 1, // 是否在文章内容显示封面图片 'digest' => '这里是文章摘要', 'content' => '这里是文章内容,你可以放很长的内容', - 'source_url' => 'https://easywechat.com', + 'source_url' => 'https://www.easywechat.com', ]); // 指定更新多图文中的第 2 篇 @@ -230,7 +230,7 @@ $stats = $app->material->stats(); // } ``` -### 删除永久素材 +### 删除永久素材; ```php $app->material->delete($mediaId); diff --git a/vendor/w7corp/easywechat/docs/src/5.x/official-account/oauth.md b/vendor/w7corp/easywechat/docs/src/5.x/official-account/oauth.md index f4a35b4a6..66ff72eb9 100755 --- a/vendor/w7corp/easywechat/docs/src/5.x/official-account/oauth.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/official-account/oauth.md @@ -127,7 +127,7 @@ $user = $app->oauth->userFromCode($code); 我们这里来用原生 PHP 写法举个例子,`oauth_callback` 是我们的授权回调 URL (未 urlencode 编码的 URL), `user/profile` 是我们需要授权才能访问的页面,它的 PHP 代码如下: ```php -// http://easywechat.com/user/profile +// http://easywechat.org/user/profile 115.32375, "latitude" => 25.097486, "photo_list" => array( - array("photo_url" => "https://easywechat.com"), - array("photo_url" => "https://easywechat.com"), + array("photo_url" => "https://XXX.com"), + array("photo_url" => "https://XXX.com"), ), "recommend" => "麦辣鸡腿堡套餐,麦乐鸡,全家桶", "special" => "免费 wifi,外卖服务", diff --git a/vendor/w7corp/easywechat/docs/src/5.x/official-account/template_message.md b/vendor/w7corp/easywechat/docs/src/5.x/official-account/template_message.md index 9f6d31a21..b48d94cf3 100755 --- a/vendor/w7corp/easywechat/docs/src/5.x/official-account/template_message.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/official-account/template_message.md @@ -40,7 +40,7 @@ $app->template_message->deletePrivateTemplate($templateId); $app->template_message->send([ 'touser' => 'user-openid', 'template_id' => 'template-id', - 'url' => 'https://easywechat.com', + 'url' => 'https://easywechat.org', 'miniprogram' => [ 'appid' => 'xxxxxxx', 'pagepath' => 'pages/xxx', @@ -52,7 +52,6 @@ $app->template_message->send([ ], ]); ``` - > 如果 url 和 miniprogram 字段都传,会优先跳转小程序。 ## 发送一次性订阅消息 @@ -61,7 +60,7 @@ $app->template_message->send([ $app->template_message->sendSubscription([ 'touser' => 'user-openid', 'template_id' => 'template-id', - 'url' => 'https://easywechat.com', + 'url' => 'https://easywechat.org', 'scene' => 1000, 'data' => [ 'key1' => 'VALUE', diff --git a/vendor/w7corp/easywechat/docs/src/5.x/open-platform/authorizer-delegate.md b/vendor/w7corp/easywechat/docs/src/5.x/open-platform/authorizer-delegate.md index 86ca4f461..c145d4fbb 100755 --- a/vendor/w7corp/easywechat/docs/src/5.x/open-platform/authorizer-delegate.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/open-platform/authorizer-delegate.md @@ -25,7 +25,7 @@ $miniProgram = $openPlatform->miniProgram(string $appId, string $refreshToken); > $appId 为授权方公众号 APPID,非开放平台第三方平台 APPID > -> $refreshToken 为授权方的 refresh_token,可通过 [获取授权方授权信息](https://easywechat.com/docs/master/open-platform/index#heading-h2-2) 接口获得。 +> $refreshToken 为授权方的 refresh_token,可通过 [获取授权方授权信息](https://www.easywechat.com/docs/master/open-platform/index#heading-h2-2) 接口获得。 ### 帮助授权方管理开放平台账号 @@ -51,11 +51,11 @@ $result = $account->getBinding(); > 授权第三方平台注册的开放平台帐号只可用于获取用户 unionid 实现用户身份打通。 > -> 第三方平台不可操作(包括绑定/解绑)通过 open.weixin.qq.com 线上流程注册的开放平台帐号。 +> 第三方平台不可操作(包括绑定/解绑)通过 open.weixin.qq.com 线上流程注册的开放平台帐号。 > -> 公众号只可将此权限集授权给一个第三方平台,授权互斥。 +> 公众号只可将此权限集授权给一个第三方平台,授权互斥。 -接下来的 API 调用等操作和公众号、小程序的开发一致,请移步到[公众号](https://easywechat.com/docs/master/official-account/index)或[小程序](https://easywechat.com/docs/master/mini-program/index)开发章节继续进行开发吧。 +接下来的 API 调用等操作和公众号、小程序的开发一致,请移步到[公众号](https://www.easywechat.com/docs/master/official-account/index)或[小程序](https://www.easywechat.com/docs/master/mini-program/index)开发章节继续进行开发吧。 ### 代码示例 diff --git a/vendor/w7corp/easywechat/docs/src/5.x/overview.md b/vendor/w7corp/easywechat/docs/src/5.x/overview.md index a5abcbdc3..90d0b69a4 100755 --- a/vendor/w7corp/easywechat/docs/src/5.x/overview.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/overview.md @@ -28,7 +28,7 @@ EasyWeChat 的安装非常简单,因为它是一个标准的 [Composer](https: ### 开始之前 -我们提供了视频教程: 当然,我还是建议你具备以下基础知识,否则可能没有那么快上手。 +我们提供了视频教程:https://www.easywechat.com/tutorials 当然,我还是建议你具备以下基础知识,否则可能没有那么快上手。 本 SDK 不是一个全新再造的东西,所以我不会从 0 开始教会你开发微信,你完全有必要在使用本 SDK 前做好以下工作: @@ -43,8 +43,8 @@ EasyWeChat 的安装非常简单,因为它是一个标准的 [Composer](https: 另外你有必要看一下以下的链接: -> - -> - +> - https://learnku.com/laravel/t/535/assertion-people-who-do-not-understand-the-wisdom-of-asking-questions-will-not-graduate-from-junior-programmers +> - http://laravel-china.github.io/php-the-right-way/ 如果你在群里问以下类似的问题,这真的是你没有做好上面的工作: diff --git a/vendor/w7corp/easywechat/docs/src/5.x/payment/order.md b/vendor/w7corp/easywechat/docs/src/5.x/payment/order.md index a55844c96..7516daab9 100755 --- a/vendor/w7corp/easywechat/docs/src/5.x/payment/order.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/payment/order.md @@ -53,7 +53,7 @@ $result = $app->order->unify([ 'plan_id' => 123,// 协议模板id 'contract_code' => 100001256,// 签约协议号 'contract_display_account' => '腾讯充值中心',// 签约用户的名称 - 'contract_notify_url' => 'http://easywechat.com/contract_notify' + 'contract_notify_url' => 'http://easywechat.org/contract_notify' ], $isContract); //$result: diff --git a/vendor/w7corp/easywechat/docs/src/5.x/payment/scan-pay.md b/vendor/w7corp/easywechat/docs/src/5.x/payment/scan-pay.md index a6eac7bce..f1642aec3 100755 --- a/vendor/w7corp/easywechat/docs/src/5.x/payment/scan-pay.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/payment/scan-pay.md @@ -2,7 +2,7 @@ ### 模式一:先生成产品二维码,扫码下单后支付 -> 请务必先熟悉流程: +> 请务必先熟悉流程:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 #### 生成产品二维码内容 @@ -14,13 +14,13 @@ $content = $app->scheme($productId); // $productId 为你的产品/商品ID, 将 `$content` 生成二维码,SDK 并不内置二维码生成库,使用你熟悉的工具创建二维码即可,比如 PHP 部分有以下工具可以选择: -> - -> - -> - +> - https://github.com/endroid/qr-code +> - https://github.com/SimpleSoftwareIO/simple-qrcode +> - https://github.com/aferrandini/PHPQRCode #### 处理回调 -当用户扫码时,你的回调接口会收到一个通知,调用[统一下单接口](https://easywechat.com/5.x/payment/order)创建订单后返回 `prepay_id`,你可以使用下面的代码处理扫码通知: +当用户扫码时,你的回调接口会收到一个通知,调用[统一下单接口](https://www.easywechat.com/5.x/payment/order)创建订单后返回 `prepay_id`,你可以使用下面的代码处理扫码通知: ```php // 扫码支付通知接收第三个参数 `$alert`,如果触发该函数,会返回“业务错误”到微信服务器,触发 `$fail` 则返回“通信错误” @@ -39,15 +39,15 @@ $response = $app->handleScannedNotify(function ($message, $fail, $alert) use ($a $response->send(); ``` -用户在手机上付完钱以后,你会再收到**付款结果通知**,这时候请参考:[处理微信支付通知](https://easywechat.com/5.x/payment/notify) 更新您的订单状态。 +用户在手机上付完钱以后,你会再收到**付款结果通知**,这时候请参考:[处理微信支付通知](https://www.easywechat.com/5.x/payment/notify) 更新您的订单状态。 ### 模式二:先下单,生成订单后创建二维码 -> : +> :https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 #### 根据用户选购的商品生成订单 -调用[统一下单接口](https://easywechat.com/5.x/payment/order)创建订单: +调用[统一下单接口](https://www.easywechat.com/5.x/payment/order)创建订单: ```php $result = $app->order->unify([ @@ -67,4 +67,4 @@ $result = $app->order->unify([ #### 支付通知 -这种方式的通知就只有**付款结果通知**了,这时候请参考:[处理微信支付通知](https://easywechat.com/5.x/payment/notify) 更新您的订单状态。 +这种方式的通知就只有**付款结果通知**了,这时候请参考:[处理微信支付通知](https://www.easywechat.com/5.x/payment/notify) 更新您的订单状态。 diff --git a/vendor/w7corp/easywechat/docs/src/5.x/wework/group-robot.md b/vendor/w7corp/easywechat/docs/src/5.x/wework/group-robot.md index 6d18af0bb..305d47291 100644 --- a/vendor/w7corp/easywechat/docs/src/5.x/wework/group-robot.md +++ b/vendor/w7corp/easywechat/docs/src/5.x/wework/group-robot.md @@ -1,12 +1,11 @@ # 群机器人 ## 使用说明 - 使用前必须先在群组里面添加机器人,然后将 `Webhook 地址` 中的 `key` 取出来,作为示例中 `$groupKey` 的值。 -> Webhook 地址示例: +> Webhook 地址示例:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=`ab4f609a-3feb-427c-ae9d-b319ca712d36` -> 微信文档: +> 微信文档:https://work.weixin.qq.com/api/doc#90000/90136/91770 ## 发送文本类型消息 @@ -101,7 +100,7 @@ $items = [ new NewsItem([ 'title' => '中秋节礼品领取', 'description' => '今年中秋节公司有豪礼相送', - 'url' => 'https://easywechat.com', + 'url' => 'https://www.easywechat.com', 'image' => 'http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png', ]), diff --git a/vendor/w7corp/easywechat/docs/src/6.x/client.md b/vendor/w7corp/easywechat/docs/src/6.x/client.md index 99e1b5e51..facdd002c 100644 --- a/vendor/w7corp/easywechat/docs/src/6.x/client.md +++ b/vendor/w7corp/easywechat/docs/src/6.x/client.md @@ -39,7 +39,7 @@ delete(string $uri, array $options = []): Symfony\Contracts\HttpClient\ResponseI ### GET ```php -$response = $api->get('/cgi-bin/user/list', [ +$response = $api->get('/cgi-bin/user/list', [ 'next_openid' => 'OPENID1', ]); ``` diff --git a/vendor/w7corp/easywechat/docs/src/6.x/index.md b/vendor/w7corp/easywechat/docs/src/6.x/index.md index 87db69a64..0f2e3fcb6 100755 --- a/vendor/w7corp/easywechat/docs/src/6.x/index.md +++ b/vendor/w7corp/easywechat/docs/src/6.x/index.md @@ -1,6 +1,5 @@ > 👋🏼 您当前浏览的文档为 6.x,其它版本的文档请参考:[5.x](/5.x/)、[4.x](/4.x/)、[3.x](/3.x/) - # EasyWeChat EasyWeChat 是一个开源的 [微信](http://www.wechat.com) 非官方 SDK。安装非常简单,因为它是一个标准的 [Composer](https://getcomposer.org/) 包,这意味着任何满足下列安装条件的 PHP 项目支持 Composer 都可以使用它。 @@ -15,11 +14,6 @@ EasyWeChat 是一个开源的 [微信](http://www.wechat.com) 非官方 SDK。 ## 安装 -::: warning -阿里云的 Composer 源已经停止维护,请停止使用,或更换官方源,或者[腾讯软件源](https://mirrors.tencent.com/help/composer.html) -::: - - ```shell composer require w7corp/easywechat:^6.7 ``` diff --git a/vendor/w7corp/easywechat/docs/src/6.x/mini-app/config.md b/vendor/w7corp/easywechat/docs/src/6.x/mini-app/config.md index 0ad908651..42a07c54b 100644 --- a/vendor/w7corp/easywechat/docs/src/6.x/mini-app/config.md +++ b/vendor/w7corp/easywechat/docs/src/6.x/mini-app/config.md @@ -14,14 +14,6 @@ 'token' => 'your-token', // Token 'aes_key' => '', // EncodingAESKey,兼容与安全模式下请一定要填写!!! - /** - * 是否使用 Stable Access Token - * 默认 false - * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html - * true 使用 false 不使用 - */ - 'use_stable_access_token' => false, - /** * 接口请求相关配置,超时时间等,具体可用参数请参考: * https://github.com/symfony/symfony/blob/5.3/src/Symfony/Contracts/HttpClient/HttpClientInterface.php diff --git a/vendor/w7corp/easywechat/docs/src/6.x/oauth.md b/vendor/w7corp/easywechat/docs/src/6.x/oauth.md index 420b287f9..207cf6767 100755 --- a/vendor/w7corp/easywechat/docs/src/6.x/oauth.md +++ b/vendor/w7corp/easywechat/docs/src/6.x/oauth.md @@ -27,12 +27,12 @@ OAuth 是一个关于授权(authorization)的开放网络标准,在全世 > - **公众平台网页授权获取用户信息** -**授权 URL**: `https://open.weixin.qq.com/connect/oauth2/authorize` +**授权 URL**: `https://open.weixin.qq.com/connect/oauth2/authorize` **Scopes**: `snsapi_base` 与 `snsapi_userinfo` > - **开放平台网页登录** -**授权 URL**: `https://open.weixin.qq.com/connect/qrconnect` +**授权 URL**: `https://open.weixin.qq.com/connect/qrconnect` **Scopes**: `snsapi_login` 他们的逻辑都一样: @@ -101,14 +101,14 @@ $user = $oauth->userFromCode($code); - `$user->getNickname(); ` 对应微信的 `nickname` - `$user->getName(); ` 对应微信的 `nickname` - `$user->getAvatar(); ` 头像地址 -- `$user->getRaw(); ` 原始 API 返回的结果 +- ~~`$user->getRaw(); ` 原始 API 返回的结果~~ - `$user->getAccessToken(); ` `access_token` - `$user->getRefreshToken(); ` `refresh_token` - `$user->getExpiresIn(); ` `expires_in`,Access Token 过期时间 - `$user->getTokenResponse(); ` 返回 `access_token` 时的响应值 > `$user` 里没有`openid`, `$user->id` 便是 `openid`. -> 如果你想拿微信返回给你的原样的全部信息,请使用:$user->getRaw(); +> 如果你想拿微信返回给你的原样的全部信息,请使用:~~$user->getRaw();~~$user->getAttributes(); 当 `scope` 为 `snsapi_base` 时 `$oauth->userFromCode($code);` 对象里只有 `id`,没有其它信息。 @@ -117,7 +117,7 @@ $user = $oauth->userFromCode($code); 我们这里来用公众号原生 PHP 写法举个例子,`oauth_callback` 是我们的授权回调 URL (未 urlencode 编码的 URL), `user/profile` 是我们需要授权才能访问的页面,它的 PHP 代码如下: ```php -// http://easywechat.com/user/profile +// http://easywechat.org/user/profile 'your-token', // Token 'aes_key' => '', // EncodingAESKey,兼容与安全模式下请一定要填写!!! - /** - * 是否使用 Stable Access Token - * 默认 false - * https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/getStableAccessToken.html - * true 使用 false 不使用 - */ - 'use_stable_access_token' => false, - /** * OAuth 配置 * diff --git a/vendor/w7corp/easywechat/docs/src/6.x/official-account/examples.md b/vendor/w7corp/easywechat/docs/src/6.x/official-account/examples.md index 2e470d257..f6dea7c7f 100644 --- a/vendor/w7corp/easywechat/docs/src/6.x/official-account/examples.md +++ b/vendor/w7corp/easywechat/docs/src/6.x/official-account/examples.md @@ -2,39 +2,6 @@ > 👏🏻 欢迎点击本页下方 "帮助我们改善此页面!" 链接参与贡献更多的使用示例! -
- webman 服务端验证消息 - -```php -get(), $request->post(), [], $request->cookie(), [], [], $request->rawBody()); - $symfony_request->headers = new HeaderBag($request->header()); - $app->setRequestFromSymfonyRequest($symfony_request); - $server = $app->getServer(); - $response = $server->serve(); - - return response($response->getBody()); - } -} -``` - -